安卓 ItemTouchHelper实现滑动删除和移动

ItemTouchHelper

详细的内容可以自己搜索,这里就简单说下个人理解

是一个可以实现拖拽listview内部组件以实现位置交换、删除等功能的一个工具类

这个类的简单实现可以分为4步(纯个人理解)

  1. 创建ItemTouchHelper.Callback的子类
  2. 编写需要实现的两个方法(移动交换位置 和 滑动删除)的接口(可以不写,直接跳转到第三步)
  3. 用自己的Adapter实现接口(覆写两个方法)
  4. 在类的onCreateView方法内调用

ItemTouchHelper子类的编写

public class ItemTouchCallback extends ItemTouchHelper.Callback {

        private CrimeAdapter mCrimeAdapter;

        public ItemTouchCallback(CrimeAdapter crimeAdapter) {
            this.mCrimeAdapter = crimeAdapter;
        }

        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            //允许上下的拖动
            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            //只允许从右向左侧滑
            int swipeFlags = ItemTouchHelper.LEFT;
            return makeMovementFlags(dragFlags, swipeFlags);
        }

        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {

            mCrimeAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
            return true;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {

            mCrimeAdapter.onItemDismiss(viewHolder.getAdapterPosition());//调用我们自定义的方法
        }

        @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);
            if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
                //滑动时改变Item的透明度
                final float alpha = 1 - Math.abs(dX) / (float)viewHolder.itemView.getWidth();
                viewHolder.itemView.setAlpha(alpha);
            }
        }
    }

这里主要实现了ItemTouchHelper的一些方法,对个性化定制要求不高的话可以不用怎么修改

编写接口

    public interface IOperationData {
        /**
         * 数据交换
         * @param fromPosition
         * @param toPosition
         */
        void onItemMove(int fromPosition,int toPosition);

        /**
         * 数据删除
         * @param position
         */
        void onItemDismiss(int position);
    }

只是告诉自己需要实现哪些方法,让代码结构更清晰,增加可读性

Adapter实现接口

    private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> implements IOperationData {

        private List<Crime> mCrimes;

        public CrimeAdapter(List<Crime> crimes) {
            mCrimes = crimes;

        }

        @Override
        public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());

            return new CrimeHolder(layoutInflater, parent);
        }

        @Override
        public void onBindViewHolder(CrimeHolder holder, int position) {
            Crime crime = mCrimes.get(position);
            holder.bind(crime);
        }

        @Override
        public int getItemCount() {
            return mCrimes.size();
        }

        public void setCrimes(List<Crime> crimes) {
            mCrimes = crimes;
        }

                @Override
        public void onItemMove(int fromPosition, int toPosition) {
            //交换位置
            Collections.swap(mCrimes,fromPosition,toPosition);
            notifyItemMoved(fromPosition,toPosition);
        }

        @Override
        public void onItemDismiss(int position) {
            //移除数据
            CrimeLab.get(getActivity()).deleterCrime(mCrimes.get(position));
            mCrimes.remove(position);
            notifyItemRemoved(position);
        }
    }

这里移除数据时因为涉及到了数据库操作,如果不需要操作数据库的话可以省掉onItemDismiss()第一句话;
交换位置的话只实现了暂时修改位置,对于需要持久化修改位置的同学,可能需要在数据库方面自己琢磨一下(因为只是一份作业所以我摸了!)

调用

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_crime_list, container, false);

        mCrimeRecyclerView = (RecyclerView) view
                .findViewById(R.id.crime_recycler_view);
        mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        if (savedInstanceState != null) {
            mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
        }


        updateUI();

        //调用ItemTouchHelper
        ItemTouchCallback callback = new ItemTouchCallback(mAdapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(mCrimeRecyclerView);

        return view;
    }

在我的多次尝试下,将调用的代码放在这个位置可以完美适配我的项目结构!(其他地方都会闪退)
具体的原因我也不是很清楚…如果项目结构不一样的同学可以参考一下下面的代码(gitee那个)或者自己多试几次,应该能找到合适的位置
(如果有知道原因的同学可以留言滴滴我!)

参考文章及代码:
  • https://blog.csdn.net/u014133119/article/details/80942932
  • https://gitee.com/Android5x/itemtouchhelperdemo?_from=gitee_search
全文代码(放送给有需要的同学)
  • https://gitee.com/luckku/CriminalIntent-ItemTouchHelper

希望这篇文章对你有帮助,这里是乐彧!
(有没有信工的同学来抄作业…?速速留言滴滴我)

上一篇:java – JTextArea在其他JFrame中显示实时控制台输出


下一篇:【spring security】认证授权实现