时隔许久,我又要更博了,含蓄的话不多说了,今天我们的主题是这个RecyclerView。至于为什么要加个scrollBar?因为我的业务需求是需要一个实现成这样的,

效果图:(可能看起来比较粗糙,但功能实现了,你可以自定义修改嘛~哈哈哈)

可能我比较老派,我的app 中list的垂直布局还是喜欢用listView ,使用起来简单(可能博主我之前有个通用的adapter不舍得放弃吧,虽然RecyclerView也有通用的adapter,但总感觉显示简单的列表要多写几行代码,有点麻烦,哈哈哈,可能我就想偷懒吧)

但既然今天的是这个RecyclerView那么我们就开始详细的说明下吧~废话不多说切入正题。

注意:我这个View暂时只实现了垂直的View的ScrollBar的滚动,暂时没有横向实现,

未来可能我会拓展,敬请期待吧(大佬可能觉得太简单,勿喷,求教,谢谢)

先说下我的思路:

一、初始思路(想一个新玩意总得有个过程和弯路嘛),可能跟你想法一样哦

  1. 用一个LinearLayout 布局套住 RecyclerView 和一个自定义的View
  2. 自定义一个可以上下滚动的scrollBar
  3. 滚动的ScrollBar绑定RecyclerView的滚动事件
  4. Ok

二、现在的实现的思路 (我想了下如果用上面的方案实现的话就,必须写个xml文件,自定义一个ViewGroup,别人使用起来会很麻烦,当然你把他当成类库来用也很简单,而我就不想写xml)

  1. HobbyRecyclerView继承RecyclerView, 扩展这个功能
  2. 在HobbyRecyclerView 中先让子view的宽度缩小 ,留出给scrollBar的宽度
  3. 在HobbyRecyclerView中画一个ScrollBar ,这个bar的高度 = (view的可见高度 / view的所有子View的高度)* view可见高度 。
  4. 给HobbyRecyclerView加上滚动事件监听,监听滚动距离dy*(view的可见高度 / view的所有子View的高度)=  scrollbar 的滚动距离
  5. 给scrollBar加上监听,监听拖动距离转化为    RecyclerView的滚动距离   =   (scrollBar的拖动距离/scrollBar可滚动的区域高度(这里的区域高度等于View的高度)) * view的所有子View的高度
  6. 测试ok

思路也大概说了,那么就来看代码的实现吧。

/**
* @author mdm
* @Description HobbyRecyclerView
* @Version 1.0
*/
public class HobbyRecyclerView extends RecyclerView { private RectF mRangeRectf;
private Paint mRangPaint;
private int showMode = 1;
//滚动条宽高
private float scrollBarHeight;
private float scrollBarWidth;
//柱间隙
private float scrollWidthSpace ;
//滚动条宽度的等分比例
private int scrollWidthWeight = 10;
//Y轴的偏移值
private float yScrollOffset = 0;
//所有的子view的总高度 也就是这个
private float childViewAllHeight;
//可视区域的高度 其实这里就是View高度
private float visualHeight;
//可视区域的高度/所有的子view的总高度 得出的比例
float range;
//recyclerView的每个Item项的宽度
private int childWidth;
//判断触摸焦点
private boolean isFocus = false; //手触摸时点的x,y坐标
float x = 0;
float y = 0; public HobbyRecyclerView(@NonNull Context context) {
super(context);
}
public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context,attrs);
}
/**
* 初始化
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
mRangeRectf = new RectF();
// region = new Region();
mRangPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRangPaint.setStyle(Paint.Style.FILL);
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.HobbyRecyclerView);
showMode = ta.getInteger(R.styleable.HobbyRecyclerView_scrollBarMode,1);
ta.recycle();
addOnScrollListener(onScrollListener);
} @Override
protected void onMeasure(int widthSpec, int heightSpec) {
if(showMode != 1){
int width = MeasureSpec.getSize(widthSpec);
scrollBarWidth = width / scrollWidthWeight;//取10分之一
scrollWidthSpace = scrollBarWidth / 10; //获取间隙
childWidth = (int) (width - scrollBarWidth);
scrollBarWidth = scrollBarWidth - 2 * scrollWidthSpace;
for (int i = 0; i < getChildCount(); i++) {
measureChild(getChildAt(i),childWidth,heightSpec);
getChildAt(i).getLayoutParams().width = childWidth;
}
setMeasuredDimension(width,heightSpec);
}else {
super.onMeasure(widthSpec, heightSpec);
} }
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
visualHeight = getMeasuredHeight();
childViewAllHeight = getChildAt(2).getHeight() * getAdapter().getItemCount();
range = 0;
if(childViewAllHeight != 0){
range = visualHeight / childViewAllHeight;
}
scrollBarHeight = range * visualHeight;
} @Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
drawRange(canvas);
} private void drawRange(Canvas canvas){
if(canvas == null) return;
mRangeRectf.set(childWidth + scrollWidthSpace,yScrollOffset,childWidth + scrollBarWidth ,yScrollOffset + scrollBarHeight);
if(isFocus) {
mRangPaint.setColor(Color.parseColor("#2386BF"));
}else{
mRangPaint.setColor(Color.parseColor("#2EB3FF"));
}
canvas.drawRect(mRangeRectf,mRangPaint);
Log.i("tag" , "yScrollOffset ------- " + yScrollOffset);
Log.i("tag" , "scrollBarHeight ------- " + scrollBarHeight);
Log.i("tag" , "yScrollOffset ------- " + yScrollOffset);
} private RecyclerView.OnScrollListener onScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
} @Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
yScrollOffset += dy * range;
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//获取屏幕上点击的坐标
x = event.getX();
y = event.getY();
if(x >= mRangeRectf.left
&& x <= mRangeRectf.right
&& y >= mRangeRectf.top
&& y <= mRangeRectf.bottom){
isFocus = true;
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
if(x >= mRangeRectf.left
&& x <= mRangeRectf.right
&& y >= mRangeRectf.top
&& y <= mRangeRectf.bottom){
float diffValue = event.getY() - y;
scrollBy(0, (int) ((diffValue/visualHeight) * childViewAllHeight));
y = event.getY();
}
break;
case MotionEvent.ACTION_UP:
isFocus = false;
invalidate();
break;
}
if(x >= childWidth
&& x <= getMeasuredWidth()
&& y >= 0
&& y <= getMeasuredHeight()){
return true;
}else return super.onTouchEvent(event);
} /**
* //当前RcyclerView显示区域的高度。水平列表屏幕从左侧到右侧显示范围
int extent = this.computeHorizontalScrollExtent(); //整体的高度,注意是整体,包括在显示区域之外的。
int range = this.computeHorizontalScrollRange(); //已经向下滚动的距离,为0时表示已处于顶部。
int offset = this.computeHorizontalScrollOffset();
*/
}

是不是很简单呢?

ok有什么问题自己看吧。如果你看到最后几行注释了,那么你会疑问,那是因为我看了这个文章

仿拼多多可水平滚动RecyclerView,自定义滚动条滚动距离

如何给RecyclerView加上滚动条--现在就教你的更多相关文章

  1. CSS 页面顶部阴影和给浏览器强制加上滚动条

    /*给浏览器强制加上滚动条*/ html{height: 101%;} /*页面顶部阴影*/ body:before{ content: ""; position: fixed; ...

  2. delphi Timage 加上滚动条方法

    elphi Timage 加上滚动条方法 1:将  Timage 放入 TScrollBox内,即   [1]设image1.parent:= ScrollBox1;   [2]在Object Ins ...

  3. Android开发15——给TextView加上滚动条

    给TextView加上滚动条非常简单,只需要把TextView标签放在ScrollView标签中 <ScrollView android:layout_width="wrap_cont ...

  4. [Android Pro] 完美解决隐藏Listview和RecyclerView去掉滚动条和滑动到边界阴影的方案

    reference to : http://blog.csdn.net/ming2316780/article/details/51578621 一.首先是Listview的属性设置 设置滑动到顶部和 ...

  5. 高分辨率下IE浏览器缩放导致出现右侧滚动条问题的解决

    0 问题描述 由于需要演示触控操作,采购了SurfacePro,SurfacePro的推荐分辨率为2736×1824,且默认缩放比例为200%,IE浏览器的默认缩放比例也是200%,这样就导致右侧出现 ...

  6. 谷歌下设置滚动条的css样式

    .oLi-lists-scroll::-webkit-scrollbar { width:5px;  padding:1px; background:url(../images/repeat-bar. ...

  7. RecyclerView.ItemDecoration

    decoration 英文意思: 英[ˌdekəˈreɪʃn] 美[ˌdɛkəˈreʃən] n. 装饰品; 装饰,装潢; 装饰图案,装饰风格; 奖章; [例句]The decoration and ...

  8. 在RecyclerView列表滚动的时候显示或者隐藏Toolbar

    先看一下效果: 本文将讲解如何实现类似于Google+应用中,当列表滚动的时候,ToolBar(以及悬浮操作按钮)的显示与隐藏(向下滚动隐藏,向上滚动显示),这种效果在Material Design ...

  9. IE6下出现横向滚动条问题的解决方案

    当我们在css样式设置为html {overflow-y:auto;}时,在ie7以上版本应用时不会有问题,可是在ie6下就会发现垂直滚动条出现会引起横向滚动条出现.究其原因是在ie6下,当内容过多出 ...

随机推荐

  1. [Javascript] Automate the process of flattening deeply nested arrays using ES2019's flat method

    Among the features introduced to the language of JavaScript in ES2019 is Array.prototype.flat. In th ...

  2. EffectiveJava(27)优先考虑使用泛型方法

    泛型方法也可以从泛型类中获得同等收益,泛型方法的转换也十分简单,只需将原生态类型改为泛型,基本就可以解决问题 如:一个返回两个集合的联合 public static Set union(Set s1, ...

  3. ES6常用对象操作整理

    const 简单类型数据常量 // const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动.对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因 ...

  4. C# 调用bat文件

    引入名称空间: using System.Diagnostics; Process proc = null; try { string targetDir = string.Format(@" ...

  5. SQL面试题: 数据库中有A B C三列,用SQL语句实现:当A列大于B列时选择A列否则选择B列 ,当B列大于C列时选择B列否则选择C列 ,

    1.用一条sql语句 select (case when a>b then a else b end ),(case when b>c then b esle c end)  from 表 ...

  6. MongoDB Query 判断为空 取值为空的时间

    if (!string.IsNullOrEmpty(STATES)) { DateTime? dtnull = null; //Return if (STATES == "Return&qu ...

  7. android 签名、混淆打包

    1.android 签名 使用eclipse导出带签名的apk,最简单的方式. 最后一步finish ,就能导出一个xxx.keystore的文件了. 下次再发布新版本的时候,使用这个生成的签名继续使 ...

  8. 删除Git记录里的大文件

    删除Git记录里的大文件 仓库自身的增长 大多数版本控制系统存储的是一组初始文件,以及每个文件随着时间的演进而逐步积累起来的差异:而 Git 则会把文件的每一个差异化版本都记录在案.这意味着,即使你只 ...

  9. Centos下运行定时任务Crontab命令介绍

    1.Cron的启动与关闭 因为Cron是Linux的内置服务.能够用下面的方法启动.关闭这个服务: /sbin/service crond start           //启动服务 /sbin/s ...

  10. 关于Animator获取当前剪辑长度

    通常下意识的肯定用这个接口 GetCurrentAnimatorStateInfo().length 但是存在一个过渡动画的问题,具体看这篇:过渡动画的测试 所以当播新的状态时直接取动画时间,取到的就 ...