Android RecyclerView ItemTouchHelper、自定义LayoutManager
程序员文章站
2022-05-10 08:17:02
绝对的recycler view进阶使用,又精炼简单,get了新技能。
静态界面,自定义layout manager,因为recycler view的layout由layout...
绝对的recycler view进阶使用,又精炼简单,get了新技能。
静态界面,自定义layout manager,因为recycler view的layout由layout manager托管
public class MyLayoutManager extends RecyclerView.LayoutManager{ public static final int MAX_SHOWN_COUNT = 4; public static final float SCALE = 0.05f; public static final int TRANS_Y = 30;//需要dp2px //其实非常简单 就是layout (RecyclerView的layout是交给lm托管的) //第一步只是一次性layout 所以动不起来(因为layout应该还负责移动) @Override public RecyclerView.LayoutParams generateDefaultLayoutParams() { return new RecyclerView.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { detachAndScrapAttachedViews(recycler);//报废所有view到recycler里 int itemCount = getItemCount(); if (itemCount >= MAX_SHOWN_COUNT) { //为什么是最后4个?因为第一个item放在最下面,一张张放上去的 for (int position = itemCount - MAX_SHOWN_COUNT; position < itemCount; position ++) { View view = recycler.getViewForPosition(position); addView(view); measureChildWithMargins(view, 0, 0); int widthSpace = getWidth() - getDecoratedMeasuredWidth(view); int heightSpace = getHeight() - getDecoratedMeasuredHeight(view); //居中 layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2, widthSpace / 2 + getDecoratedMeasuredWidth(view), heightSpace / 2 + getDecoratedMeasuredHeight(view)); //顶层scale=1 translationY=0 //每一级scale相差0.05f translationY=7dp //拖动时,顶层scale不变,-1层scale慢慢变为1,transY慢慢变为0(这句话先不考虑) //-2层变成-1层 //-3层scale变化,tranY不变 int level = itemCount - position - 1; //顶层不需要变化 if (level > 0) { //每一层都要scale变化 view.setScaleX(1 - SCALE * level); if (level < MAX_SHOWN_COUNT - 1) { view.setTranslationY(TRANS_Y * level); view.setScaleY(1 - SCALE * level); } else { view.setTranslationY(TRANS_Y * (level - 1)); view.setScaleY(1 - SCALE * (level - 1)); } } } } } }
动态界面,重写item touch helper callback
class CallBack extends ItemTouchHelper.SimpleCallback { public CallBack(int dragDirs, int swipeDirs) { super(dragDirs, swipeDirs); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { String s = list.remove(viewHolder.getLayoutPosition()); list.add(0,s); adapter.notifyDataSetChanged(); } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); double swipeValue = Math.sqrt(dX * dX + dY * dY); double fraction = swipeValue / (getSwipeThreshold(viewHolder) * recyclerView.getWidth());//阈值 if (fraction > 1) { fraction = 1; } int childCount = recyclerView.getChildCount(); for (int i = 0; i < childCount; i ++) { View child = recyclerView.getChildAt(i); int level = childCount - i - 1; if (level > 0) { child.setScaleX((float) (1-SCALE * level + fraction * SCALE)); if (level < MAX_SHOWN_COUNT - 1) { child.setScaleY((float) (1 - SCALE * level + fraction * SCALE)); child.setTranslationY((float) (TRANS_Y * level - fraction * TRANS_Y)); } } } } }
使用
CallBack callBack = new CallBack(0, ItemTouchHelper.DOWN | ItemTouchHelper.UP | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT); ItemTouchHelper helper = new ItemTouchHelper(callBack); helper.attachToRecyclerView(rv);
动画。item touch helper帮你做的工作就是
1.让当前item可拖拽,在item一半的区域被拖到外面时(作者自定义了阈值),移除
2.移除后,下面的view进行补充动画
这里我们需要增加一个补充动画的过度,原生动画太生硬了
就是重写的call back中的onChildDraw
@Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); double swipeValue = Math.sqrt(dX * dX + dY * dY); double fraction = swipeValue / (getSwipeThreshold(viewHolder) * recyclerView.getWidth());//阈值 if (fraction > 1) { fraction = 1; } int childCount = recyclerView.getChildCount(); for (int i = 0; i < childCount; i ++) { View child = recyclerView.getChildAt(i); int level = childCount - i - 1; if (level > 0) { child.setScaleX((float) (1-SCALE * level + fraction * SCALE)); if (level < MAX_SHOWN_COUNT - 1) { child.setScaleY((float) (1 - SCALE * level + fraction * SCALE)); child.setTranslationY((float) (TRANS_Y * level - fraction * TRANS_Y)); } } } }
上一篇: 3个字节破解一个小游戏
下一篇: 黑客在暗网销售651,894份医疗记录
推荐阅读
-
android中RecyclerView自定义分割线实现
-
Android RecyclerView ItemTouchHelper、自定义LayoutManager
-
Android嵌套RecyclerView左右滑动替代自定义view
-
Android自定义RecyclerView实现不固定刻度的刻度尺
-
Android 自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁
-
Android中自定义RecyclerView.ItemDecoration
-
Android自定义下拉刷新控件for RecyclerView详情
-
关于Android RecyclerView的那些开源LayoutManager
-
Android自定义recyclerView实现时光轴效果
-
有焦点 item 的水平/垂直滚动 RecyclerView-LayoutManager。仿 Android 豆瓣书影音“推荐“频道列表布局