使用Kotlin实现UC头条ViewPager左右滑动效果
2017-02-16 11:24
543 查看
转载请标明出处:一片枫叶的专栏
上一篇文章中我们讲解了一个使用的多行文本显示控件,在实际开发过程中我们时常会遇到这种需求:有两个TextView控件分行显示,当第一个TextView的内容过多一行显示不下时,我们需要将第二个TextView在第一个TextView的第二行末尾显示,当第二个TextView第二行也显示不下时,第一个TextView的第二行结尾以“…”结束,第二个TextView显示在第二行的最后段,而上一篇文章介绍的就是一个实现这种需求的自定义控件。
而本文我们将介绍一个使用kotlin实现的仿照UC头条ViewPager的左右滑动效果。这个项目是为了学习kotlin的使用以及基本语法,在实现的过程中主要需要注意的有两点:一个是UC头条在滑动过程中的遮盖动画效果,一个是跨多个Tab点击屏蔽多个页面滑动效果。
本项目的github地址:android-xmviewpager,欢迎star和follow。
在介绍具体的使用说明之前,我们先看一下简单的实现效果:
![](https://img-blog.csdn.net/20160922095746542)
实现说明
本项目是通过TabLayout+ViewPager的方式实现的,这里我们首先看一下整个页面的布局文件的实现方式:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[/code]
可以发现其是通过TabLayout和ViewPager的方式实现的,在实现过程中由于要求点击跨多个Tab的时候屏蔽多次滑动效果,这里重写了TabLayout的onTabSelectedListener监听:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
[/code]
然后我们可以继续看一下初始化数据的实现:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[/code]
好吧,这其中需要注意的是:viewPager的setCurrentItem方法,表示会将viewPager的当前显示Item设置为指定的item,而我们可以发现这里的setCurrentItem有两个参数,第一个参数,是显示当前Item的position,而第二个参数为boolean类型,表示是否有滑动效果,比如当前我们在ViewPager的第一项,而我们点击了TabLayout的第八项,这时候如果我们调用了:setCurrentItem(8, true),它表示我们将滑动到ViewPager的第八项,且有滚动效果。这样我们做一下变通,当我们点击的TabLayout与当前Item的距离大于一个Item的时候就先滑动到当前Item的前一个并且没有滑动效果,然后在执行一次setCurrentItem方法,这样在跨多个Tab点击的时候就屏蔽了多个Item滚动的效果了。
在实现过程中还需要实现滑动覆盖的效果,一开始想了很久包括使用ViewPager的setPageTransformer方法,但是还是没法实现这个思路,后来经过同事指点,终于搞定了。就是对ViewPager每一项item中的子View执行动画效果,这样就会实现需求的动画效果了。
以下是自己重写的setPageTransformer类:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[/code]
可以看到在我们自定义的PageTransformer中,我们通过findViewById方法获取了滑动Item的子View,并对子View执行translationX操作,进而实现了滑动Item的遮盖效果。
另外由于本文主要介绍Kotlin的使用,更多关于Kotlin的相关知识点,可参考:
Basic Syntax - Kotlin Programing
Kotlin:Android事件的Swift
Kotlin在Android工程中的应用
当然更具体的关于本控件的实现可以下载源码参考。
总结:
以上就是通过Kotlin实现的仿照UC头条ViewPager左右滑动效果的小项目。当然现在还很不完善,对于源码有兴趣的同学可以到github上看一下具体实现。项目地址:android-xmviewpager
另外对github项目,开源项目解析感兴趣的同学可以参考我的:
Github项目解析(一)–>上传Android项目至github
Github项目解析(二)–>将Android项目发布至JCenter代码库
Github项目解析(三)–>Android内存泄露监测之leakcanary
Github项目解析(四)–>动态更改TextView的字体大小
Github项目解析(五)–>Android日志框架
Github项目解析(六)–>自定义实现ButterKnife框架
Github项目解析(七)–>防止按钮重复点击
Github项目解析(八)–>Activity启动过程中获取组件宽高的五种方式
Github项目解析(九)–>实现Activity跳转动画的五种方式
Github项目解析(十)–>几行代码快速集成二维码扫描库
Github项目解析(十一)–>一个简单,强大的自定义广告活动弹窗
Github项目解析(十二)–>一个简单的多行文本显示控件
(function () {('pre.prettyprint code').each(function () {
var lines = (this).text().split(′\n′).length;varnumbering = $('').addClass('pre-numbering').hide();
(this).addClass(′has−numbering′).parent().append(numbering);
for (i = 1; i
上一篇文章中我们讲解了一个使用的多行文本显示控件,在实际开发过程中我们时常会遇到这种需求:有两个TextView控件分行显示,当第一个TextView的内容过多一行显示不下时,我们需要将第二个TextView在第一个TextView的第二行末尾显示,当第二个TextView第二行也显示不下时,第一个TextView的第二行结尾以“…”结束,第二个TextView显示在第二行的最后段,而上一篇文章介绍的就是一个实现这种需求的自定义控件。
而本文我们将介绍一个使用kotlin实现的仿照UC头条ViewPager的左右滑动效果。这个项目是为了学习kotlin的使用以及基本语法,在实现的过程中主要需要注意的有两点:一个是UC头条在滑动过程中的遮盖动画效果,一个是跨多个Tab点击屏蔽多个页面滑动效果。
本项目的github地址:android-xmviewpager,欢迎star和follow。
在介绍具体的使用说明之前,我们先看一下简单的实现效果:
实现说明
本项目是通过TabLayout+ViewPager的方式实现的,这里我们首先看一下整个页面的布局文件的实现方式:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".java.TabLayoutActivity" android:orientation="vertical"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIndicatorColor="#ADBE107E" app:tabIndicatorHeight="0dp" app:tabMode="scrollable" app:tabPadding="0dp" /> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </LinearLayout>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[/code]
可以发现其是通过TabLayout和ViewPager的方式实现的,在实现过程中由于要求点击跨多个Tab的时候屏蔽多次滑动效果,这里重写了TabLayout的onTabSelectedListener监听:
/** * 自定义函数, : Unit 表示函数没有返回值 */ fun initViewPager() : Unit { /** * 获取初始化数据 */ val titles = ViewData().getTitles() /** * as 类似于java中的类型强转 */ val toolbar = findViewById(R.id.toolbar) as Toolbar setSupportActionBar(toolbar) mViewPager = findViewById(R.id.viewpager) as ViewPager mTabLayout = findViewById(R.id.tabs) as TabLayout /** * 通过 in 关键字实现循环遍历 * 在调用mTabLayou变量的方法时,由于mTabLayout可能为空,所以在调用方法时添加!! * titles[] 与 titles.get 方法的功能是一样的 * titles.indices 获取的是数组的下标 */ for (i in titles.indices) { mTabLayout!!.addTab(mTabLayout!!.newTab().setText(titles[i])) } val fragments = ArrayList<Fragment>() /** * 循环遍历添加ViewPager的Fragment */ for (i in titles.indices) { val listFragment = MListFragment() val bundle = Bundle() val sb = StringBuffer() for (j in 1..8) { sb.append(titles[i]).append(" ") } bundle.putString("content", sb.toString()) listFragment.arguments = bundle fragments.add(listFragment) } val mFragmentAdapteradapter = MFragmentAdapter(supportFragmentManager, fragments, titles) mViewPager!!.adapter = mFragmentAdapteradapter mViewPager!!.adapter = mFragmentAdapteradapter mTabLayout!!.setupWithViewPager(mViewPager) mTabLayout!!.setTabsFromPagerAdapter(mFragmentAdapteradapter) /** * 自定义设置ViewPager切换动画 */ mViewPager!!.setPageTransformer(true, MTransformer()) /** * 通过object : TabLayout.OnTabSelectedListener 的方式创建内部匿名类(这里主要是接口) */ mTabLayout!!.setOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabReselected(tab: TabLayout.Tab?) { } override fun onTabUnselected(tab: TabLayout.Tab?) { } override fun onTabSelected(tab: TabLayout.Tab?) { /** * 控制变量 */ if (isOk) { isOk = false val currentItemIndex = mViewPager!!.currentItem if (Math.abs(currentItemIndex - tab!!.position) > 1) { /** * 向后点击 */ if (currentItemIndex <= tab!!.position) { mViewPager!!.setCurrentItem(tab.position - 1, false) mViewPager!!.setCurrentItem(tab.position, true) } /** * 向前点击 */ else { mViewPager!!.setCurrentItem(tab.position + 1, false) mViewPager!!.setCurrentItem(tab.position, true) } } else { mViewPager!!.setCurrentItem(tab.position, true) } isOk = true } } }) }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
[/code]
然后我们可以继续看一下初始化数据的实现:
/** * Created by aaron on 16/9/14. * 主要用于保存界面ViewPager数据 */ class ViewData { /** * 该方法用于获取ViewPager TAB 显示数据 */ fun getTitles() : ArrayList<String> { /** * 通过类名创建该类的对象,这里直接调用java中的集合框架 */ val titles = ArrayList<String>() titles.clear() titles.add("推荐") titles.add("视频") titles.add("热点") titles.add("娱乐") titles.add("体育") titles.add("北京") titles.add("财经") titles.add("科技") titles.add("汽车") titles.add("社会") titles.add("搞笑") titles.add("军事") titles.add("历史") titles.add("涨知识") titles.add("NBA") titles.add("两性") return titles } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[/code]
好吧,这其中需要注意的是:viewPager的setCurrentItem方法,表示会将viewPager的当前显示Item设置为指定的item,而我们可以发现这里的setCurrentItem有两个参数,第一个参数,是显示当前Item的position,而第二个参数为boolean类型,表示是否有滑动效果,比如当前我们在ViewPager的第一项,而我们点击了TabLayout的第八项,这时候如果我们调用了:setCurrentItem(8, true),它表示我们将滑动到ViewPager的第八项,且有滚动效果。这样我们做一下变通,当我们点击的TabLayout与当前Item的距离大于一个Item的时候就先滑动到当前Item的前一个并且没有滑动效果,然后在执行一次setCurrentItem方法,这样在跨多个Tab点击的时候就屏蔽了多个Item滚动的效果了。
在实现过程中还需要实现滑动覆盖的效果,一开始想了很久包括使用ViewPager的setPageTransformer方法,但是还是没法实现这个思路,后来经过同事指点,终于搞定了。就是对ViewPager每一项item中的子View执行动画效果,这样就会实现需求的动画效果了。
以下是自己重写的setPageTransformer类:
/** * Created by aaron on 16/9/13. * 自定义实现ViewPager的切换动画效果 */ class MTransformer : ViewPager.PageTransformer { /** * 回调方法,重写viewpager的切换动画 */ override fun transformPage(view: View, position: Float) { val pageWidth = view.width val wallpaper = view.findViewById(R.id.recycler_view) if (position < -1) { // [-Infinity,-1) wallpaper.translationX = 0.toFloat() view.translationX = 0.toFloat() } else if (position <= 1) { // [-1,1] wallpaper.translationX = pageWidth * getFactor(position) view.translationX = 8 * position } else { // (1,+Infinity] wallpaper.translationX = 0.toFloat() view.translationX = 0.toFloat() } } private fun getFactor(position: Float): Float { return -position / 2 } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
![](http://static.blog.csdn.net/images/save_snippets.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[/code]
可以看到在我们自定义的PageTransformer中,我们通过findViewById方法获取了滑动Item的子View,并对子View执行translationX操作,进而实现了滑动Item的遮盖效果。
另外由于本文主要介绍Kotlin的使用,更多关于Kotlin的相关知识点,可参考:
Basic Syntax - Kotlin Programing
Kotlin:Android事件的Swift
Kotlin在Android工程中的应用
当然更具体的关于本控件的实现可以下载源码参考。
总结:
以上就是通过Kotlin实现的仿照UC头条ViewPager左右滑动效果的小项目。当然现在还很不完善,对于源码有兴趣的同学可以到github上看一下具体实现。项目地址:android-xmviewpager
另外对github项目,开源项目解析感兴趣的同学可以参考我的:
Github项目解析(一)–>上传Android项目至github
Github项目解析(二)–>将Android项目发布至JCenter代码库
Github项目解析(三)–>Android内存泄露监测之leakcanary
Github项目解析(四)–>动态更改TextView的字体大小
Github项目解析(五)–>Android日志框架
Github项目解析(六)–>自定义实现ButterKnife框架
Github项目解析(七)–>防止按钮重复点击
Github项目解析(八)–>Activity启动过程中获取组件宽高的五种方式
Github项目解析(九)–>实现Activity跳转动画的五种方式
Github项目解析(十)–>几行代码快速集成二维码扫描库
Github项目解析(十一)–>一个简单,强大的自定义广告活动弹窗
Github项目解析(十二)–>一个简单的多行文本显示控件
(function () {('pre.prettyprint code').each(function () {
var lines = (this).text().split(′\n′).length;varnumbering = $('').addClass('pre-numbering').hide();
(this).addClass(′has−numbering′).parent().append(numbering);
for (i = 1; i
相关文章推荐
- flex 控件的重要属性
- 学习Winform文本类控件(Label、Button、TextBox)
- Delphi控件ListView的属性及使用方法详解
- web下载的ActiveX控件自动更新
- WinForm实现按名称递归查找控件的方法
- C#中父窗口和子窗口之间控件互操作实例
- C#编写ActiveX网页截图控件
- Android App开发中ViewPager组件的入门使用教程
- Android编程之Button控件用法实例分析
- Android控件之CheckBox、RadioButton用法实例分析
- 在Android开发中使用自定义组合控件的例子
- 一款超酷的Android自定义加载控件
- 直接拿来用的Android刮奖控件
- Android重写View实现全新的控件
- MFC中动态创建控件以及事件响应实现方法
- WinForm自定义函数FindControl实现按名称查找控件
- Android控件之ProgressBar用法实例分析
- C#向Word文档中添加内容控件的方法示例
- WinForm拖拽控件生成副本的解决方法
- ASP.NET动态添加用户控件的方法