SeniorUI24_ItemTouchHelper实现陌陌滑动移除效果

SeniorUI_高级UI汇总目录

一 效果图

在这里插入图片描述

二 需求

  • 一组包含图片的组件,依次显示,陌陌的滑动删除效果
  • 最上面只显示一张图片和内容,下面预加载几张,能够看到预加载的边框部分,其他被最上面遮盖
  • 向上、下、左、右触摸滑动一段距离,当前卡片的内容会被移除
  • 手指滑动距离不足时,恢复原先效果
  • 随着滑动,后面要加载的项会缩放,有一个“向上浮现”的效果

三 需求分析

  • RecyclerView展示列表数据
  • 自定义LayoutManager重写onLayoutChildren实现每一项数据的显示摆放
  • 实现ItemTouchHelper.SimpleCallback用于和用户进行交互,对拖拽进行处理
  • SimpleCallback的onChildDraw方法控制每个child的绘制,在其绘制之前对每个child进行动画效果从而实现缩放、平移

四 关键代码

SwipeCardLayoutManager

public class SwipeCardLayoutManager extends RecyclerView.LayoutManager {
    @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) {
//        super.onLayoutChildren(recycler, state);
        //h缓存的核心机制之一
        detachAndScrapAttachedViews(recycler);

        int itemCount = getItemCount();
        int initPosition;
        if (itemCount < CardConfig.MAX_SHOW_COUNT) {
            initPosition = 0;
        } else {
            initPosition = itemCount - CardConfig.MAX_SHOW_COUNT;
        }

        for (int position = initPosition; position < itemCount; position++) {
            //从缓存获取view
            View view = recycler.getViewForPosition(position);
            addView(view);
            measureChild(view, 0, 0);

            int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
            int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);

            layoutDecorated(view,
                    widthSpace/2,
                    heightSpace/2,
                    widthSpace/2 + getDecoratedMeasuredWidth(view),
                    heightSpace/2 + getDecoratedMeasuredHeight(view));
            // 均匀的缩放和位移
            int level = itemCount - position - 1;
            if (level > 0) {
                view.setScaleX(1 - CardConfig.SCALE_GAP * level);
                view.setScaleY(1- CardConfig.SCALE_GAP * level);
                if (level < CardConfig.MAX_SHOW_COUNT -1) {
                    view.setTranslationY(CardConfig.TRANS_Y_GAP* level);
                } else {
                    view.setTranslationY(CardConfig.TRANS_Y_GAP* (level - 1));
                }

            }
        }

    }
}

SwipeCardCallback

public class SwipeCardCallback extends ItemTouchHelper.SimpleCallback {

    private RecyclerView mRv;
    private RecyclerView.Adapter mAdapter;
    private List mDatas;

    public SwipeCardCallback(int dragDirs, int swipeDirs, RecyclerView.Adapter adapter, List datas,
                             RecyclerView recyclerView) {
        super(0, ItemTouchHelper.DOWN | ItemTouchHelper.UP | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT);
        mRv = recyclerView;
        mAdapter = adapter;
        mDatas = datas;
    }


    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        Object object = mDatas.remove(viewHolder.getLayoutPosition());
        mDatas.add(0, object);
        mAdapter.notifyItemMoved(viewHolder.getLayoutPosition(), 0);
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        double maxDistance = recyclerView.getWidth() * 0.5f;
        double distance = Math.sqrt(dX * dX + dY * dY);
        double fraction = distance / maxDistance;

        if (fraction > 1) {
            fraction = 1;
        }

        int itemCount = recyclerView.getChildCount();
        for (int i = 0; i < itemCount; i++) {
            View view = recyclerView.getChildAt(i);

            int level = itemCount - i - 1;
            if (level >= 0) {
                if (level < CardConfig.MAX_SHOW_COUNT -1) {
                    view.setTranslationY((float) (CardConfig.TRANS_Y_GAP *level - fraction * CardConfig.TRANS_Y_GAP));
                    view.setScaleX((float) (1 - CardConfig.SCALE_GAP * level + fraction *CardConfig.SCALE_GAP));
                    view.setScaleY((float) (1 - CardConfig.SCALE_GAP * level + fraction *CardConfig.SCALE_GAP));
//                    view.setAlpha((float) (1 - 0.1 * level + fraction *CardConfig.SCALE_GAP));
                } else if (level == CardConfig.MAX_SHOW_COUNT -1){ // 控制的是最下层的Item
                    view.setTranslationY((float) (CardConfig.TRANS_Y_GAP *(level -1)));
                    view.setScaleX((float) (1 - CardConfig.SCALE_GAP * (level- 1)));
                    view.setScaleY((float) (1 - CardConfig.SCALE_GAP * (level -1)));
                }
            }
        }

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }

    @Override
    public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
        return 100;
    }

    @Override
    public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
        return 0.5f;
    }
}

五 Demo

RecyclerViewSwipeCardActivity

发布了211 篇原创文章 · 获赞 63 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/baopengjian/article/details/103493625