美文网首页
Android--自定义LayoutManager实现层叠卡片效

Android--自定义LayoutManager实现层叠卡片效

作者: aruba | 来源:发表于2020-03-05 15:43 被阅读0次
    效果如下:
    cardRecyclerView.gif
    首先自定义LayouManager,实现自己摆放控件
    public class CardLayoutManager extends RecyclerView.LayoutManager {
        @Override
        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
            return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
        }
    
        /**
         * 自定义LayoutManager核心是摆放控件,所以onLayoutChildren方法是我们要改写的核心
         *
         * @param recycler
         * @param state
         */
        @Override
        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            //缓存
            detachAndScrapAttachedViews(recycler);
    
            //获取所有item(包括不可见的)个数
            int count = getItemCount();
            //由于我们是倒序摆放,所以初始索引从后面开始
            int initIndex = count - CardConfig.SHOW_MAX_COUNT;
            if (initIndex < 0) {
                initIndex = 0;
            }
    
            for (int i = initIndex; i < count; i++) {
                //从缓存中获取view
                View view = recycler.getViewForPosition(i);
                //添加到recyclerView
                addView(view);
                //测量一下view
                measureChild(view, 0, 0);
    
                //居中摆放,getDecoratedMeasuredWidth方法是获取带分割线的宽度,比直接使用view.getWidth()精确
                int realWidth = getDecoratedMeasuredWidth(view);
                int realHeight = getDecoratedMeasuredHeight(view);
                int widthPadding = (int) ((getWidth() - realWidth) / 2f);
                int heightPadding = (int) ((getHeight() - realHeight) / 2f);
    
                //摆放child
                layoutDecorated(view, widthPadding, heightPadding,
                        widthPadding + realWidth, heightPadding + realHeight);
                //根据索引,来位移和缩放child
                int level = count - i - 1;
                //level范围(CardConfig.SHOW_MAX_COUNT-1)- 0
                // 最下层的不动和最后第二层重叠
                if (level == CardConfig.SHOW_MAX_COUNT - 1) {
                    level--;
                }
                view.setTranslationY(level * CardConfig.TRANSLATION_Y);
                view.setScaleX(1 - level * CardConfig.SCALE);
                view.setScaleY(1 - level * CardConfig.SCALE);
            }
        }
    }
    
    然后利用ItemTouchHelper,对item的移动进行计算,并对每个item进行属性设置
    public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {
    
        private List<String> mDatas;
        private RecyclerView.Adapter mAdapter;
    
        public ItemTouchHelperCallback(List<String> mDatas, RecyclerView.Adapter mAdapter) {
            this.mDatas = mDatas;
            this.mAdapter = mAdapter;
        }
    
        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
    
            return makeMovementFlags(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.UP | ItemTouchHelper.DOWN);
        }
    
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
            return false;
        }
    
        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
            String s = mDatas.remove(viewHolder.getLayoutPosition());
            mDatas.add(0, s);
            mAdapter.notifyDataSetChanged();
        }
    
        @Override
        public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
            //计算移动距离
            float distance = (float) Math.hypot(dX, dY);
            float maxDistance = recyclerView.getWidth() / 2f;
    
            //比例
            float fraction = distance / maxDistance;
            if (fraction > 1) {
                fraction = 1;
            }
            //为每个child执行动画
            int count = recyclerView.getChildCount();
    
            for (int i = 0; i < count; i++) {
                //获取的view从下层到上层
                View view = recyclerView.getChildAt(i);
    
                int level = CardConfig.SHOW_MAX_COUNT - i - 1;
                //level范围(CardConfig.SHOW_MAX_COUNT-1)-0,每个child最大只移动一个CardConfig.TRANSLATION_Y和放大CardConfig.SCALE
    
                if (level == CardConfig.SHOW_MAX_COUNT - 1) { // 最下层的不动和最后第二层重叠
                    view.setTranslationY(CardConfig.TRANSLATION_Y * (level - 1));
                    view.setScaleX(1 - CardConfig.SCALE * (level - 1));
                    view.setScaleY(1 - CardConfig.SCALE * (level - 1));
                } else if (level > 0) {
                    view.setTranslationY(level * CardConfig.TRANSLATION_Y - fraction * CardConfig.TRANSLATION_Y);
                    view.setScaleX(1 - level * CardConfig.SCALE + fraction * CardConfig.SCALE);
                    view.setScaleY(1 - level * CardConfig.SCALE + fraction * CardConfig.SCALE);
                }
            }
    
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        }
    
        @Override
        public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
            return 0.3f;
        }
    }
    
    再设置给RecyclerView
    public class MainActivity extends AppCompatActivity {
        RecyclerView rv;
        List<String> mStrings = new ArrayList<>();
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            rv = (RecyclerView) findViewById(R.id.rv);
            rv.setLayoutManager(new CardLayoutManager());
            
            for (int i = 1; i < 21; i++) {
                mStrings.add(String.valueOf(i));
            }
            MyAdapter myAdapter = new MyAdapter(this, mStrings);
            rv.setAdapter(myAdapter);
    
            ItemTouchHelperCallback itemTouchHelperCallback = new ItemTouchHelperCallback(mStrings, myAdapter);
            ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
            itemTouchHelper.attachToRecyclerView(rv);
        }
    
        class MyAdapter extends RecyclerView.Adapter {
            private Context mContext;
            private List<String> mStrings;
    
            public MyAdapter(Context mContext, List<String> mStrings) {
                this.mContext = mContext;
                this.mStrings = mStrings;
            }
    
            @NonNull
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
                return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_recyclerview, viewGroup, false));
            }
    
            @Override
            public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
                MyViewHolder myViewHolder = (MyViewHolder) viewHolder;
                myViewHolder.textView.setText(mStrings.get(i) + "/" + getItemCount());
            }
    
            @Override
            public int getItemCount() {
                return mStrings.size();
            }
    
            class MyViewHolder extends RecyclerView.ViewHolder {
                public TextView textView;
    
                public MyViewHolder(@NonNull View itemView) {
                    super(itemView);
                    textView = itemView.findViewById(R.id.tv);
                }
            }
        }
    }
    
    项目地址:https://gitee.com/aruba/CardMoveApplication.git

    相关文章

      网友评论

          本文标题:Android--自定义LayoutManager实现层叠卡片效

          本文链接:https://www.haomeiwen.com/subject/argtrhtx.html