转载请标明出处:一片枫叶的专栏

上一篇文章中我们讲解了一个使用的多行文本显示控件,在实际开发过程中我们时常会遇到这种需求:有两个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.AppBarLayoutandroid:id="@+id/appbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"><android.support.v7.widget.Toolbarandroid: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.TabLayoutandroid: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.ViewPagerandroid: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
  • 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

可以发现其是通过TabLayout和ViewPager的方式实现的,在实现过程中由于要求点击跨多个Tab的时候屏蔽多次滑动效果,这里重写了TabLayout的onTabSelectedListener监听:

/*** 自定义函数, : Unit 表示函数没有返回值*/fun initViewPager() : Unit {/*** 获取初始化数据*/val titles = ViewData().getTitles()/*** as 类似于java中的类型强转*/val toolbar = findViewById(R.id.toolbar) as ToolbarsetSupportActionBar(toolbar)mViewPager = findViewById(R.id.viewpager) as ViewPagermTabLayout = 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 = bundlefragments.add(listFragment)}val mFragmentAdapteradapter = MFragmentAdapter(supportFragmentManager, fragments, titles)mViewPager!!.adapter = mFragmentAdapteradaptermViewPager!!.adapter = mFragmentAdapteradaptermTabLayout!!.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 = falseval currentItemIndex = mViewPager!!.currentItemif (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
  • 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

然后我们可以继续看一下初始化数据的实现:

/*** 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
  • 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

好吧,这其中需要注意的是: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.widthval 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
  • 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

可以看到在我们自定义的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 () {(function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(′\n′).length;var(this).text().split('\n').length;var numbering = $('').addClass('pre-numbering').hide(); (this).addClass(′has−numbering′).parent().append((this).addClass('has-numbering').parent().append(numbering); for (i = 1; i

使用Kotlin实现UC头条ViewPager左右滑动效果相关推荐

  1. 自定义ViewGroup实现ViewPager的滑动效果

    看下他的 布局 文件: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout andr ...

  2. 禁用ViewPager边界滑动效果(转)

    反射设置方法 1 private EdgeEffectCompat leftEdge; 2 private EdgeEffectCompat rightEdge; 3 public void Disa ...

  3. ViewPager之使用PagerTabStrip添加标题栏,实现滑动效果

    1.首先,转自: (1).<ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同> 这篇文章写得不错,大家可以参考一下. (2). ...

  4. android 打造炫酷导航栏(仿UC头条)

    年后开始上班甚是清闲,所以想捣鼓一些东西.在翻阅大神杰作Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI 的时候看到下面有一条评论说,如果导航栏能滑动就更好了. ...

  5. UC浏览器主界面滑动折叠效果 使用自定义behavior实现 难度五颗星*****

    思路:!!!!!!!!!!! RcycleView上的HeadScrollBehavior 思路: 1.让recycleview居于头部的下方 ---方案: 重写layoutDependsOn  让当 ...

  6. SwipeRefreshLayout源码分析+自定义UC头条下拉刷新Demo

    首先来看SwipeRefreshLayout(以下简称SR)的继承关系 NestedScrollingParent:嵌套滑动父接口 NestedScrollingChild :嵌套滑动子接口 Andr ...

  7. Android WebView与ViewPager的滑动冲突分析

    前言 如题所述,我使用的架构是ViewPager+Fragment+WebView进行开发的,由于WebView的html页面代码是第三方的,这里不好放出来,所以只能放一个大致的架构图,如图所示,Vi ...

  8. android ViewPager 不带滑动效果切换item

    其实这是很简单的,但是今晚脑袋晕乎乎的 绕了一大圈,记录一下 以警同类人. 只需要在setCurrentItem传参数时这么写:mViewPager.setCurrentItem(item序号,fal ...

  9. ViewPager相互嵌套,导致子ViewPager无法滑动,且子ViewPager中的view无法被点击

        场景:当使用ViewPager进行嵌套的时候,子viewPager是无法进行嵌套的,因此我们要重写ViewPager类,并重写里层viewPager类中的onTouchEvent方法,调用其父 ...

最新文章

  1. Java的SPI机制
  2. 第十三届光华工程科技奖公布,彭士禄、张伯礼、王海峰等40人及1个团体获奖
  3. 随机模拟【1】:随机模拟的研究范围与特征
  4. ML之DT之CART:分类与回归树CART算法的简介、应用、经典案例之详细攻略
  5. 给ButtonBar组件设置自定义TOOLTIP。
  6. linux 漏洞数量,Debian Linux被列为过去20年漏洞数量最多的操作系统
  7. mtk android 5.1 logo,Android ROM DIY之MTK平台手机通用移植
  8. python脚本运行命令_从Python脚本运行shell命令
  9. 一部影响美国网络安全政策的电影
  10. Apache Flink 1.9.0 为什么将支持 Python API ?
  11. Redis(RedisTemplate)使用hash哈希
  12. 你会用 JSON.stringify()? JSON.stringify一些坑
  13. python简单编程--ATM银行管理系统
  14. 笔记-软考高项-错题笔记汇总4
  15. 如何区分冲突域和广播域?
  16. 这些书你读过一多半,你就是编程大牛!
  17. 【免费】各种hadoop版本对应的hadoop.dll和winutils.exe
  18. Python中的shuffle()函数
  19. 如何用OpenCV改变图片的大小?
  20. 【Hibernate步步为营】--映射合集汇总

热门文章

  1. 大公司项目开发到上线流程
  2. Ubuntu 调用查看USB摄像头命令行介绍
  3. windows python删除文件文件夹报错:PermissionError
  4. 利用Tampermonkey chrome插件写脚本抢课以及交大选课插件
  5. 图片上传下载-功能实现
  6. 用python做一个车牌识别_如何用 Python 识别车牌
  7. 一次电商系统搭建过程的分享
  8. flutter dart list 遍历数据
  9. 探索性数据分析的思路整理
  10. mysql 统计历史累计数据,每天的数据需要进行累加