其实它的原理和listview差不多,但是架构更好,拓展性更强,它的滑动用的是view.offsetTopAndBottom,改变的是top和bottom的值
它的复用依然是用detach和attach来完成的,复用还是有个复用容器,叫recycler和recyclerpool
它将布局的责任交给了LayoutManager,而它自己负责大局的调度
所以我们可以定义自己的LayoutManager,比如实现探探的卡片效果
另外还有ItemTouchHelper,这个类很有用,可以用来自定义滑动效果,有drag和swipe两种操作
还有Recycleview .ItemDecoration,用来画分割线
还有Recycleview.ItemAnimator,定义view被添加,移动,删除时的动画
Recycleview.OnItemTouchListener可以用来拦截触摸事件,定义自己的滑动行为,ItemTouchHelper内部就实现了这个接口
还有OpRecorder,用来管理adapter的数据变化,比如添加,删除,移动,在RecyclerView的initAdapterManager()中初始化
其实drag效果是监听触摸事件,然后进行item的滑动,这是第一步。第二步实现其他item的移动动画,是通过adapter的notifyItemMoved,而里面的动画实现是依靠改变每个item的位置参数,最后调用requestLayout来实现的
支持drag和swipe两个事件,都支持四个方向。
public void attachHelper(){
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ListCallback());
itemTouchHelper.attachToRecyclerView(recycer);
}
public class ListCallback extends ItemTouchHelper.Callback{
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP|ItemTouchHelper.DOWN;
int swipeFlags =ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
int i = makeMovementFlags(dragFlags, swipeFlags);
return i;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.i(TAG, "onMove: ");//位置不一样时才调用
adapter.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
Log.i(TAG, "onSwiped: ");//默认为滑动距离超过一半,执行移出屏幕动画,动画结束后回调这个方法
}
}
at android.view.ViewGroup.addViewInner(ViewGroup.java:4309)
at android.view.ViewGroup.addView(ViewGroup.java:4145)
at android.view.ViewGroup.addView(ViewGroup.java:4086)
at android.support.v7.widget.RecyclerView$4.addView(RecyclerView.java:544)
at android.support.v7.widget.ChildHelper.addView(ChildHelper.java:107)
at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:6314)
at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6272)
at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6260)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1385)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1334)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:563)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2847)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3145)
at android.view.View.layout(View.java:16630)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
可以重写ItemTouchHelper.Callback中的onChildDraw来实现侧滑删除,这个方法默认实现是将item进行translationX操作,在老版本中是canvas的平移,我们根据dx,dy的条件判断进行滑动限制即可
还需要重写手指抬起事件,因为默认实现是到一定速度或者滑动距离大于一个值,就进行ondismiss操作
当然你还要自己加上 上下滑动时自动关闭“delete”
当然drag操作也很好实现,你可以用GridLayoutManager,然后只允许drag操作即可
还有一种实现是当年很火的“瀑布流”,这个用StaggeredLayoutManager就能实现
网友评论