现在好多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相关推荐

  1. Android自定义ViewPager图片指示器,兼容实现底部横线指示器

    前言  记得以前自己使用过的ViewPager Indicator有JakeWharton大神的开源库ViewPagerIndicator,v4包自带的PagerTitleStrip以及Android ...

  2. viewpager 的工具类,内置多种指示器,能够帮你快速完成,轮播图,app 引导页,viewpager 的 tab 指示器等等

    ViewPagerHelper 项目地址:LillteZheng/ViewPagerHelper  简介:这是一个,viewpager 的工具类,内置多种指示器,能够帮你快速完成,轮播图,app 引导 ...

  3. 为什么我不用ViewPager或RecyclerView来做上下滑切换

    上下滑切换翻页大概是这样的效果: 目前网上有诸多如 "仿抖音上下滑..." "仿花椒映客直播..." 之类的技术分享,都有讲述实现上下滑切换页面的方案,其中以 ...

  4. TabLayout+ViewPager+Fragmet+RecyclerView结合的小demo

    前两天想熟悉一下tablayout,所以就弄了个特别简单的tablayout+viewpager+fragmet+recyclerview结合的小demo.虽然特别简单,但还是遇到了不少问题. tab ...

  5. viewpager与recyclerview

    经常有需求要求不同标签页加载的列表类型类似,比如标签1是国内新闻,标签2是国外新闻,标签3是娱乐新闻... 实际上每个列表都是相同方式加载的.为了减少控件的重新写的问题,所以用了同一个recycler ...

  6. Android之自定义ViewPager实现图片的无线轮播

    PS:以前也写过关于图片轮播这一块的博客.不过写的很烂,并且很多情况没有考虑到(没有支持无线轮播,和手势点击事件).因此这里写一篇补上.也是当时太年轻了. 注:图片请放大后再看.否则看不清楚. 学习内 ...

  7. 三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。...

    (转载请声明出处:http://www.cnblogs.com/linguanh/) 前言: 接上次分享的 ListView 动态加载类,入口:http://www.cnblogs.com/lingu ...

  8. [原创]自定义ViewPager实现3D画廊效果

    经常在群里看到有些开发者在提问:怎么实现3D画廊效果,没思路. 有人出谋划策,你重写onTouch,在里面去判断:或者你去重写滑动监听事件,滑动的时候去动态设置左右两边的图片的大小和缩放效果.可能你们 ...

  9. 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图

    仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端( ...

  10. 仿网易新闻的页面(ViewPager作为RecyclerView的Header)

    需求 > 想实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表. 本文链接 http://blog.csdn.net/never_cxb/article/ ...

最新文章

  1. R语言dim函数获取dataframe、matrix的维度、shape实战
  2. 接口测试用例设计思路
  3. oracle生成excle报表,oracle自动生成excel报表(时间为变量,条件含变量)
  4. Shell编程(逻辑判断、文件目录属性判断、if特殊用法、case判断)
  5. android反编译工具 ApkDec-Release-0.1
  6. 20200219:不同路径Ⅱ(leetcode63)
  7. cpu win10 安装yolo_Win10 超详细 0基础 搭建YOLOV5教程【环境搭建篇】
  8. apktool + dex2jar + xjad反编译apk文件
  9. SMP多核启动(二):PSCI
  10. 接入华为推送用API给iOS应用发消息时如何获取access_token?
  11. 【论文笔记】Data Shapley: Equitable Valuation of Data for Machine Learning
  12. matlab内置随机数生成器及随机模拟举例
  13. SEO优化基础知识大全 SEO新手入门必备知识
  14. 长风破浪正其时,Python天堑变通途(3)(令人智熄的分支循环,优先级问题)
  15. 手机禁止安装app,刷机才能恢复
  16. .netcore基础知识(一)
  17. html单元格分割,html – 拆分td在两个
  18. APAD 7'“谷歌Android操作系统1.5无线触摸屏
  19. 【华人学者风采】张瑞 新加坡国立大学
  20. springboot+jsp志愿者岗位报名培训系统javaweb

热门文章

  1. DCO-OFDM可见光通信matlab
  2. 至于你信不信,反正我信了
  3. 独家 | 想成为一名数据科学家?你得先读读这篇文章
  4. 【心悟水浒】带团队懂管理
  5. Python解决:从键盘输入n个数,统计非负数字的个数和非负数字的和。
  6. 哪个数据库替代oracle,关于Oracle数据库替代加密算法
  7. 【飞凌和你测评】再次进阶,更高性价比-飞凌iMX6ULL开发板
  8. 30天自制操作系统-Hello OS
  9. 使用 Learner Lab - 使用 API Gateway 与 Lambda 上传图片到 S3
  10. mysql 1556_mysqldump: Got error: 1556: You can't use locks with log tables.