RecycleView添加分割线(ItemDecoration)以及交互动画效果

1、分割线:
实现分割线的代码写在一个Activity类中,其中两个内部类重写了ItemDecoration实现分割线效果;

GridDividerItemDecoration:

这个类实现了表格分割线效果;
RecycleView添加分割线(ItemDecoration)以及交互动画效果_第1张图片

LinearDividerItemDecoration:

这个类实现类似ListView的分割线效果,支持水平和垂直方向;

package com.longshun.recycleviewdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 自定义RecycleView的ItemDecoration
 */
public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private RecyclerView.ItemDecoration itemDecoration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView) findViewById(R.id.rv);

        itemDecoration = new LinearDividerItemDecoration(this, LinearLayoutManager.VERTICAL);
        recyclerView.addItemDecoration(itemDecoration);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

        final List listStr = new ArrayList<>();
        for (int i = 0; i < 29; i++) {
            listStr.add("item" + i);
        }
        final MyAdapter adapter = new MyAdapter(this, listStr);
        recyclerView.setAdapter(adapter);

        //交互动画
        MyItemTouchHelperCallback callback = new MyItemTouchHelperCallback(new MyItemTouchHelperCallback.ItemSwipeListener() {
            @Override
            public void onItemSwipe(RecyclerView.ViewHolder viewHolder, int direction) {
                //删除数据 更新列表
                int position = viewHolder.getAdapterPosition();
                listStr.remove(position);
                adapter.notifyItemRemoved(position);
            }

            @Override
            public void onItemDrag(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                //交换数据 更新列表
                int fromPosition = viewHolder.getAdapterPosition();
                int toPosition = target.getAdapterPosition();
                Collections.swap(listStr, fromPosition, toPosition);
                adapter.notifyItemMoved(fromPosition, toPosition);
            }
        });
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }

    public void showLinear(View view) {
        recyclerView.removeItemDecoration(itemDecoration);
        itemDecoration = new LinearDividerItemDecoration(this, LinearLayoutManager.VERTICAL);
        recyclerView.addItemDecoration(itemDecoration);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    }

    public void showGrid(View view) {
        recyclerView.removeItemDecoration(itemDecoration);
        itemDecoration = new GridDividerItemDecoration(this);
        recyclerView.addItemDecoration(itemDecoration);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false));
    }

    /*适用于 RecycleView的GridLayoutManager和StaggerGridLayoutManager*/
    class GridDividerItemDecoration extends RecyclerView.ItemDecoration {

        private int[] attrs = {android.R.attr.listDivider};

        private Drawable mDividerDrawable;

        public GridDividerItemDecoration(Context context) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            this.mDividerDrawable = typedArray.getDrawable(0);
            typedArray.recycle();
        }

        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
            drawVertical(c, parent);
            drawHorizontal(c, parent);
        }

        private void drawHorizontal(Canvas c, RecyclerView parent) {
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

                int left = child.getLeft() - params.leftMargin;
                int top = child.getBottom() + params.bottomMargin;
                int right = child.getRight() + params.rightMargin;
                int bottom = top + mDividerDrawable.getIntrinsicHeight();
                //画下面的线
                mDividerDrawable.setBounds(left, top, right, bottom);
                mDividerDrawable.draw(c);

                //如果是第一行 那么画上面的线
                if (isFirstRow(parent, i)) {
                    top = child.getTop() - params.topMargin;
                    bottom = top + mDividerDrawable.getIntrinsicHeight();
                    mDividerDrawable.setBounds(left, top, right, bottom);
                    mDividerDrawable.draw(c);
                }
            }
        }

        private void drawVertical(Canvas c, RecyclerView parent) {
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

                int left = child.getRight() + params.rightMargin;
                int top = child.getTop() - params.topMargin;
                int right = left + mDividerDrawable.getIntrinsicWidth();
                int bottom = child.getBottom() + params.bottomMargin;

                //画右边的线
                mDividerDrawable.setBounds(left, top, right, bottom);
                mDividerDrawable.draw(c);

                //如果是第一列 画左边的线
                if (isFirstColumn(parent, i)) {
                    left = child.getLeft() - params.leftMargin;
                    right = left + mDividerDrawable.getIntrinsicWidth();
                    mDividerDrawable.setBounds(left, top, right, bottom);
                    mDividerDrawable.draw(c);
                }
            }
        }

        private boolean isFirstColumn(RecyclerView parent, int position) {
            int spanCount = getSpanCount(parent);
            return position % spanCount == 0;
        }

        /*是否是第一行*/
        private boolean isFirstRow(RecyclerView parent, int i) {
            int spanCount = getSpanCount(parent);
            return i <= spanCount - 1;
        }

        private int getSpanCount(RecyclerView parent) {
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof StaggeredGridLayoutManager) {
                return ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
            } else if (layoutManager instanceof GridLayoutManager) {
                return ((GridLayoutManager) layoutManager).getSpanCount();
            }
            return 0;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.set(mDividerDrawable.getIntrinsicWidth(), mDividerDrawable.getIntrinsicHeight(), mDividerDrawable.getIntrinsicWidth(), mDividerDrawable.getIntrinsicHeight());
        }
    }

    /*适用于 RecycleView的LineaLayoutManager*/
    class LinearDividerItemDecoration extends RecyclerView.ItemDecoration {

        private int[] attrs = {android.R.attr.listDivider};

        private Drawable mDividerDrawable;
        private int mOri;

        public LinearDividerItemDecoration(Context context, int ori) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            mDividerDrawable = typedArray.getDrawable(0);
            this.mOri = ori;
            typedArray.recycle();
        }

        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
            if (mOri == LinearLayoutManager.VERTICAL) {
                //画水平线 上下左右的每条分割线都看成一个小矩形,绘制每个item的矩形分割线
                int childCount = parent.getChildCount();
                for (int i = 0; i < childCount; i++) {
                    View child = parent.getChildAt(i);

                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

                    int left = child.getLeft() - params.leftMargin;
                    int top = child.getBottom() + params.bottomMargin;
                    int right = child.getRight() + params.rightMargin;
                    int bottom = top + mDividerDrawable.getIntrinsicHeight();
                    mDividerDrawable.setBounds(left, top, right, bottom);
                    mDividerDrawable.draw(c);
                }
            } else if (mOri == LinearLayoutManager.HORIZONTAL) {
                //画垂直线
                int childCount = parent.getChildCount();
                for (int i = 0; i < childCount; i++) {
                    View child = parent.getChildAt(i);
                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                    int left = child.getRight() + params.rightMargin;
                    int right = left + mDividerDrawable.getIntrinsicWidth();
                    int top = child.getTop() - params.topMargin;
                    int bottom = child.getBottom() + params.bottomMargin;
                    mDividerDrawable.setBounds(left, top, right, bottom);
                    mDividerDrawable.draw(c);
                }
            }
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            //获取每个item上下左右四边向外的偏移量 上下左右的每条分割线都看成一个小矩形
            if (mOri == LinearLayoutManager.HORIZONTAL) {
                outRect.set(0, 0, mDividerDrawable.getIntrinsicWidth(), 0);
            } else if (mOri == LinearLayoutManager.VERTICAL) {
                outRect.set(0, 0, 0, mDividerDrawable.getIntrinsicHeight());
            }
        }
    }


    class MyAdapter extends RecyclerView.Adapter {

        private Context context;
        private List listStr;

        public MyAdapter(Context context, List listStr) {
            this.context = context;
            this.listStr = listStr;
        }

        @Override
        public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
            return new MyViewHolder(view);
        }

        @Override
        public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {
            holder.tvStr.setText(listStr.get(position));
        }

        @Override
        public int getItemCount() {
            return listStr == null ? 0 : listStr.size();
        }

        class MyViewHolder extends RecyclerView.ViewHolder {

            TextView tvStr;

            public MyViewHolder(View itemView) {
                super(itemView);

                tvStr = (TextView) itemView.findViewById(android.R.id.text1);
            }
        }
    }
}

2、交互动画效果

关键类:ItemTouchHelper,ItemTouchHelper.Callback

//交互动画
        MyItemTouchHelperCallback callback = new MyItemTouchHelperCallback(new MyItemTouchHelperCallback.ItemSwipeListener() {
            @Override
            public void onItemSwipe(RecyclerView.ViewHolder viewHolder, int direction) {
                //删除数据 更新列表
                int position = viewHolder.getAdapterPosition();
                listStr.remove(position);
                adapter.notifyItemRemoved(position);
            }

            @Override
            public void onItemDrag(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                //交换数据 更新列表
                int fromPosition = viewHolder.getAdapterPosition();
                int toPosition = target.getAdapterPosition();
                Collections.swap(listStr, fromPosition, toPosition);
                adapter.notifyItemMoved(fromPosition, toPosition);
            }
        });
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
package com.longshun.recycleviewdemo;

import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;

/**
 * Created by longShun on 2017/4/22.
 */
public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private ItemSwipeListener itemSwipeListener;

    public MyItemTouchHelperCallback(ItemSwipeListener itemSwipeListener) {
        this.itemSwipeListener = itemSwipeListener;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        //设置拖动方向和滑动方向
        //上下拖动
        int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //左右滑动
        int swipeFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlag, swipeFlag);
    }

    /*拖拽移动*/
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        if (itemSwipeListener != null) {
            itemSwipeListener.onItemDrag(viewHolder, target);
        }
        return false;
    }

    /*开启长按拖拽*/
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        //滑动事件交给外部处理
        if (itemSwipeListener != null) {
            itemSwipeListener.onItemSwipe(viewHolder, direction);
        }
    }

    /*在这里做一些动画效果*/
    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        //dX 0-> +(-)viewHolder.itemView.getWidth
        float alpha= 1 - Math.abs(dX) / viewHolder.itemView.getWidth();
        viewHolder.itemView.setAlpha(alpha);
        //产生的布局复用问题 可以在这里处理
        //item滑出删除,那么透明度变化的item的布局可能会被复用
        if(alpha== 0){
            //还原布局之前的状态
            viewHolder.itemView.setAlpha(1);
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        //判断选中状态,拖动和滑动的时候 设置item的背景
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(Color.GRAY);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    //*这个方法中恢复 item的状态*/            
    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    viewHolder.itemView.setBackgroundColor(Color.WHITE);
        super.clearView(recyclerView, viewHolder);
    }

    public interface ItemSwipeListener {
        void onItemSwipe(RecyclerView.ViewHolder viewHolder, int direction);

        void onItemDrag(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target);
    }
}

你可能感兴趣的:(android)