Android RecyclerView ItemTouchHelper、自定义LayoutManager
2018-02-23 22:36
489 查看
学习自https://mp.weixin.qq.com/s/jn5JUfKhJGfoLJv88_a5qg
绝对的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 callbackclass 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));
}
}
}
}
绝对的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 callbackclass 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));
}
}
}
}
相关文章推荐
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- Android进阶七:RecyclerView拖动滑动之ItemTouchHelper
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android使用ItemTouchHelper实现RecyclerView的item拖动位置交换
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- Android使用ItemTouchHelper打造可拖拽的RecyclerView
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android RecyclerView 使用 ItemTouchHelper 时异常
- Android ItemTouchHelper实现RecyclerView交互动画
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- RecyclerView打造可拖拽的GridView使用ItemTouchHelper
- RecyclerView的拖动和滑动:基本的ItemTouchHelper示例(转)
- 使用ItemTouchHelper和RecyclerView实现拖拽移动效果
- ItemTouchHelper,让你轻松打造RecyclerView中Item的滑动删除,拖拽交换
- ItemTouchHelper,让你轻松打造RecyclerView中Item的滑动删除,拖拽交换