自定义ViewPager和RecyclerView指示器 Indicator
现在好多App首页都会有这样的条目
这种的实现方式要么是viewpager翻页滚动,要么就是recyclerView持续滚动。下面的指示器系统的太丑 ,所以就自定义了一个。下面是demo简单的效果图:
ViewPagerIndicator
因为嫌麻烦这里的指示器没有用Canvas进行绘制,用了布局文件代替:
指示器布局文件 view_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/root"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000000"><Viewandroid:id="@+id/ind_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#ff0000"/></FrameLayout>
ViewPagerIndicator.java
public class ViewPagerIndicator extends FrameLayout {private View rootView;private View indView;public ViewPagerIndicator(@NonNull Context context) {this(context, null);}public ViewPagerIndicator(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public ViewPagerIndicator(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);View root = inflate(context, R.layout.app_viewpager_indicator, this);rootView = root.findViewById(R.id.root);indView = root.findViewById(R.id.ind_view);}int indViewWidth = 0;@Overridepublic void draw(Canvas canvas) {super.draw(canvas);}public void setWithViewPager(ViewPager viewPager) {//如果没有adapter,则隐藏不显示if (null == viewPager.getAdapter()) {setVisibility(GONE);Log.e(getClass().getSimpleName(), "no adapter");return;}//获取viewPager中fragment的数量final int count = viewPager.getAdapter().getCount();if (count == 0) {return;}//加载到window之后再进行view宽度的获取rootView.post(new Runnable() {@Overridepublic void run() {//获取当前滑块的宽度indViewWidth = getWidth() / count;FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) indView.getLayoutParams();layoutParams.width = indViewWidth;indView.setLayoutParams(layoutParams);}});viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {/**** @param position* @param positionOffset [0,1]中的值,指示在位置处与页面的偏移百分比。* @param positionOffsetPixels 以像素为单位的值,表示与位置的偏移量。*/@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//获取滑块距父布局左侧的距离int left = (int) (position * indViewWidth + positionOffset * indViewWidth);//重新布局滑块viewindView.layout(left, indView.getTop(), left + indViewWidth, indView.getBottom());}@Overridepublic void onPageSelected(int position) {}@Overridepublic void onPageScrollStateChanged(int state) {}});}
}
步骤如下
1.计算出滑块的宽高
2.为viewPager添加滑动监听事件,监听滑动距离,计算出移动距离重新布局滑块
RecyclerViewIndicator
indicator 布局同上
RecyclerViewIndicator.java
public class RecyclerViewIndicator extends FrameLayout {private View rootView;private View indView;public RecyclerViewIndicator(@NonNull Context context) {this(context, null);}public RecyclerViewIndicator(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public RecyclerViewIndicator(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);View root = inflate(context, R.layout.app_viewpager_indicator, this);rootView = root.findViewById(R.id.root);indView = root.findViewById(R.id.ind_view);}int indViewWidth = 0;int indViewHeight = 0;float rate = 0f;/*** 绑定recyclerView* @param recyclerView* @param orientation 排列方向** 这里用到的recyclerView的三个方法* computeHorizontalScrollExtent/computeVerticalScrollExtent 当前显示在屏幕上的总长度* computeHorizontalScrollOffset/computeVerticalScrollOffset 当前滑动的总长度* computeHorizontalScrollRange/computeVerticalScrollRange recylerView内部的总长度*/public void setWithRecyclerView(final RecyclerView recyclerView, int orientation) {final boolean isHorizontal = orientation == RecyclerView.HORIZONTAL;rootView.post(new Runnable() {@Overridepublic void run() {float scrollRange = isHorizontal ? recyclerView.computeHorizontalScrollRange() : recyclerView.computeVerticalScrollRange();float scrollExtent = isHorizontal ? recyclerView.computeHorizontalScrollExtent() : recyclerView.computeVerticalScrollExtent();LayoutParams layoutParams = (LayoutParams) indView.getLayoutParams();if (isHorizontal) {//算出比例rate = (float) getWidth() / scrollRange;//由显示在屏幕上的总长度算出滑块长度indViewWidth = (int) (scrollExtent * rate);layoutParams.height = LayoutParams.MATCH_PARENT;layoutParams.width = indViewWidth;} else {rate = (float) getHeight() / scrollRange;layoutParams.width = LayoutParams.MATCH_PARENT;indViewHeight = (int) (scrollExtent * rate);layoutParams.height = indViewHeight;}indView.setLayoutParams(layoutParams);}});recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);int scrollOffset = isHorizontal ? recyclerView.computeHorizontalScrollOffset() : recyclerView.computeVerticalScrollOffset();//由recyclerView滑动距离算出滑块移动距咯if (isHorizontal) {int left = (int) (scrollOffset * rate);indView.layout(left, indView.getTop(), left + indViewWidth, indView.getBottom());} else {int top = (int) (scrollOffset * rate);indView.layout(indView.getLeft(), top, indView.getRight(), top + indViewHeight);}}});}
}
步骤基本上和recyclerView的实现步骤一致,
这里主要用到了recyclerView的三个方法进行计算
computeHorizontalScrollExtent/computeVerticalScrollExtent 当前显示在屏幕上的总长度
computeHorizontalScrollOffset/computeVerticalScrollOffset 当前滑动的总长度
computeHorizontalScrollRange/computeVerticalScrollRange recylerView内部的总长度
通过 orientation 来区分recyclrView 的排列方式
demo地址
demo只是做了实现的方式,界面有点丑,自己可以更改背景进行修改。也可以是用绘制的方式,添加自定义view的参数。
自定义ViewPager和RecyclerView指示器 Indicator相关推荐
- Android自定义ViewPager图片指示器,兼容实现底部横线指示器
前言 记得以前自己使用过的ViewPager Indicator有JakeWharton大神的开源库ViewPagerIndicator,v4包自带的PagerTitleStrip以及Android ...
- viewpager 的工具类,内置多种指示器,能够帮你快速完成,轮播图,app 引导页,viewpager 的 tab 指示器等等
ViewPagerHelper 项目地址:LillteZheng/ViewPagerHelper 简介:这是一个,viewpager 的工具类,内置多种指示器,能够帮你快速完成,轮播图,app 引导 ...
- 为什么我不用ViewPager或RecyclerView来做上下滑切换
上下滑切换翻页大概是这样的效果: 目前网上有诸多如 "仿抖音上下滑..." "仿花椒映客直播..." 之类的技术分享,都有讲述实现上下滑切换页面的方案,其中以 ...
- TabLayout+ViewPager+Fragmet+RecyclerView结合的小demo
前两天想熟悉一下tablayout,所以就弄了个特别简单的tablayout+viewpager+fragmet+recyclerview结合的小demo.虽然特别简单,但还是遇到了不少问题. tab ...
- viewpager与recyclerview
经常有需求要求不同标签页加载的列表类型类似,比如标签1是国内新闻,标签2是国外新闻,标签3是娱乐新闻... 实际上每个列表都是相同方式加载的.为了减少控件的重新写的问题,所以用了同一个recycler ...
- Android之自定义ViewPager实现图片的无线轮播
PS:以前也写过关于图片轮播这一块的博客.不过写的很烂,并且很多情况没有考虑到(没有支持无线轮播,和手势点击事件).因此这里写一篇补上.也是当时太年轻了. 注:图片请放大后再看.否则看不清楚. 学习内 ...
- 三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。...
(转载请声明出处:http://www.cnblogs.com/linguanh/) 前言: 接上次分享的 ListView 动态加载类,入口:http://www.cnblogs.com/lingu ...
- [原创]自定义ViewPager实现3D画廊效果
经常在群里看到有些开发者在提问:怎么实现3D画廊效果,没思路. 有人出谋划策,你重写onTouch,在里面去判断:或者你去重写滑动监听事件,滑动的时候去动态设置左右两边的图片的大小和缩放效果.可能你们 ...
- 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图
仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端( ...
- 仿网易新闻的页面(ViewPager作为RecyclerView的Header)
需求 > 想实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表. 本文链接 http://blog.csdn.net/never_cxb/article/ ...
最新文章
- R语言dim函数获取dataframe、matrix的维度、shape实战
- 接口测试用例设计思路
- oracle生成excle报表,oracle自动生成excel报表(时间为变量,条件含变量)
- Shell编程(逻辑判断、文件目录属性判断、if特殊用法、case判断)
- android反编译工具 ApkDec-Release-0.1
- 20200219:不同路径Ⅱ(leetcode63)
- cpu win10 安装yolo_Win10 超详细 0基础 搭建YOLOV5教程【环境搭建篇】
- apktool + dex2jar + xjad反编译apk文件
- SMP多核启动(二):PSCI
- 接入华为推送用API给iOS应用发消息时如何获取access_token?
- 【论文笔记】Data Shapley: Equitable Valuation of Data for Machine Learning
- matlab内置随机数生成器及随机模拟举例
- SEO优化基础知识大全 SEO新手入门必备知识
- 长风破浪正其时,Python天堑变通途(3)(令人智熄的分支循环,优先级问题)
- 手机禁止安装app,刷机才能恢复
- .netcore基础知识(一)
- html单元格分割,html – 拆分td在两个
- APAD 7'“谷歌Android操作系统1.5无线触摸屏
- 【华人学者风采】张瑞 新加坡国立大学
- springboot+jsp志愿者岗位报名培训系统javaweb
热门文章
- DCO-OFDM可见光通信matlab
- 至于你信不信,反正我信了
- 独家 | 想成为一名数据科学家?你得先读读这篇文章
- 【心悟水浒】带团队懂管理
- Python解决:从键盘输入n个数,统计非负数字的个数和非负数字的和。
- 哪个数据库替代oracle,关于Oracle数据库替代加密算法
- 【飞凌和你测评】再次进阶,更高性价比-飞凌iMX6ULL开发板
- 30天自制操作系统-Hello OS
- 使用 Learner Lab - 使用 API Gateway 与 Lambda 上传图片到 S3
- mysql 1556_mysqldump: Got error: 1556: You can't use locks with log tables.