当前位置: 移动技术网 > 移动技术>移动开发>Android > Android RecyclerView ItemTouchHelper、自定义LayoutManager

Android RecyclerView ItemTouchHelper、自定义LayoutManager

2018年03月24日  | 移动技术网移动技术  | 我要评论

绝对的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));
            }
        }
    }
}

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网