分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

Metail Design之RecyclerView

发布时间:2023-09-06 02:03责任编辑:苏小强关键词:暂无标签

1.RecyclerView简单设置:

 1 private void initRecyclerView() { 2 ????????mList = new ArrayList<>(); 3 ????????for (int i = 0; i < 60; i++) { 4 ????????????mList.add(String.format(getString(R.string.lesson),(1+i)+"")); 5 ????????} 6 ????????setLayoutManget(switchId); 7 ????????mAdapter = new MainRecyclerAdapter(mList); 8 ????????mRy.setAdapter(mAdapter); 9 ????????mRy.setItemAnimator(new DefaultItemAnimator());10 ????????mAdapter.setItemClickListener(new MainRecyclerAdapter.ItemClickListener() {11 ????????????@Override12 ????????????public void click(View view, int position, String text) {13 ????????????????Toast.makeText(MainActivity.this, "点击--" + text, Toast.LENGTH_SHORT).show();14 ????????????????goActivity(position);15 ????????????}16 ????????});17 ????}

rv是高度解耦,可以为他设置LayoutManger,ItemAnimotor,Adaper,Deliver分割线等.

2.设置条目添加,移除时可以局部刷新,尽可能优化性能:

 3.要使用StaggeredGridLayoutManager

 1).这里模拟给每个Item动态分配高度,记得使用

View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1,parent,false);
这种方式经过看源码发现没有人为的添加到父类的ViewGroup,而是交给RecyclerView自己处理
1 @Override2 ????public MainViewHold onCreateViewHolder(ViewGroup parent, int viewType) {3 // ???????View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null);//没有添加进parent4 // ???????View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, parent);//双重parent5 ????????View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1,parent,false);6 ????????return new MainViewHold(view);7 ????}

 2).上面注释两种方式有问题,第一种getLayoutParams参数为空,第二种resoure(android.R.layout.simple_list_item_1)有两个parent,因为查看源码发现root.add(view,params)添加了一次,recyclerview自己又会把item添加进入它之中.

  3).上面两种方法最终调用的是这个方法,对应的还是第三种方法

 4).上一张瀑布流的图:

 3.RecyclerView设置条目点击事件:

 方式一:采用holder.getAdaperPosition()来获得当前条目的位置信息,这种可以实时获取position信息,包括addItem和remove条目,最好应用于数据集变化的情况.

 
 
 方式二:采用自定义OnClickListener,构造方法时把position传进去,这样position在单独开辟的堆栈里,可以长久存储,最好应用于数据集不发生改变的情况(经过测试,addItem和removeItem后,postion不会实时变化)

 监听器: 

  应用于RecyclerView:

 4.RecycleView分割线:

 1).初识RecyclerView.ItemDecoration中的 getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) 

它是先于onDraw()方法执行的,调用此方法首先会获得条目之间的间隔宽度,Rect的矩形区域.获得条目的偏移量,所有条目都会调用一次该方法.
2)onDraw方法是真正绘制Divider时的方法
 
这里我们先来个简单的,绘制LinearLayoutManager的分割线
首先,可以拿系统的Divider(方便),构造方法传入布局方向

 我们可以给divider一个set方法,来动态设置

 设置所有item的偏移:

 divider绘制的位置:(根据上面)

onDraw()真正的绘制: 

计算边距:

 这里以绘制垂直方法为例,也就是长形矩形为例讲解:

这里有一点非常需要注意:

就是parent.getChildCount()方法是获得当前屏幕一屏的ChildView 数量:

(1).这里绘制的时候child的param要用RecyclerView.LayoutParam的,因为它继承与MaragLayout可以拿到Margin边距

(2).child如果有平移动画这里还要添加动画的距离:Math.round(ViewCompat.getTranslationY(child));
(3).这里记得开始和结束用c.save()和c.restore()来保存画板
(4).这里以child.getBottom)---item5为例说说,获得的值在屏幕上指的是哪里:

drawHorazotion()也是同样的原理,再讲讲我们自定义的ItemDecoration怎么应用于recyclerview:

这里说说绘制GridView布局分割线:
1).关于偏移量这里就要考虑最后一行和最后一列:

 2).这里说说如何判断最后一行最后一列:

 3).判断最后一列:

 5.RecyclerView像ListView那样添加头和尾布局:

 1).通过看ListView添加头尾的源码,它其中采用了代理模式,添加头尾的时候重新new了一个WrapHeaderListViewAdapter,里面分别用两个List<View> 来存放添加进来的头和尾,getView,getCount等方法还是使用原来adapter,或者加以修饰还是交给子类去实现,所以我们也来模仿这样:

先自己定义一个wrapHeadRecyclerAdapter:
 2).模仿着listview重写几个重要的方法:
这里获得数量是把头和尾的也添加进去了

3).通过getItemViewType来区分当前条目是什么类型(头,尾,正常条目)

 记得这里的mAdapter.getItemViewType(adjPosition)返回的是原来的正常Item,位置也是从0开始的
4).onCreateViewHolder()方法里的头尾位置new出来的hold只要是配合框架使用,其实并没什么用,viewhold的目的主要是目的是复用,而头尾直接是addView就添加进来了,不存在大量复用情况

5).onBindViewHolder

 6).使用还是跟平常rv一样使用,wrapheadrecyclerview使我们偷偷做的

 效果图:

 6.RecyclerView添加拖拽和侧滑:

 1).添加拖拽和侧滑需要用到一个ItemTouchHelper,以及ItemTouchHelper.Callback:

1 getMovementFlags()方法
 onMove()方法
onSwiped()方法
 isLongPressDragEnabled()方法:
onSelectedChanged()方法:
 clearView()方法:
onChildDraw()方法:

 2).两个不同的类之间通信,采用Interface接口做桥梁,很好的降低耦合:

public QQAdapter(List<QQMessage> list, StartDragListener startDragListener) { ???????this.list = list; ???????mStartDragListener =startDragListener; ???}holder.iv_logo.setOnTouchListener(new View.OnTouchListener() { ???????????@Override ???????????public boolean onTouch(View v, MotionEvent event) { ???????????????if (event.getAction()==MotionEvent.ACTION_DOWN){ ???????????????????mStartDragListener.onStartDrag(holder); ???????????????} ???????????????return false; ???????????} ???????});

例如:这里QQAdapter相与外界通信,通过StartDragListener 接口,把图标iv_logo按下移动时,让ItemTouchHelper调用startDrag()方法

/** * 监听Viewhold.icon按下上下拖拽的监听 */public interface StartDragListener { ???void onStartDrag(RecyclerView.ViewHolder viewHolder);}

 在Activity中这样实现:

 3).ItemTouchHelper.CallBack需要把他的拖拽和侧滑回调给QQAdapter,来改变数据集的变化和视图的变化,这里通信就只有CallBack与QQAdapter,所以可以通过ItemTouchMoveListener接口来回调出去,QQAdapter来实现接口,分别进行数据的更新和试图的变化:
MyCallBack中:

 QQAdaper中:

 都是调用的notify方法

效果图如下:

 注意:

 如图:

Metail Design之RecyclerView

原文地址:https://www.cnblogs.com/jeffery336699/p/9295360.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved