Material Design 中 RecyclerView 实现侧滑菜单及交互效果

在移动端应用中,侧滑菜单是一种常见的交互方式。在 Material Design 中,RecyclerView 提供了一种简单的方式来实现侧滑菜单及交互效果。

RecyclerView 简介

RecyclerView 是 Android 原生的一个控件,它是 ListView 的升级版。与 ListView 相比,RecyclerView 更加灵活,可以自定义布局和动画效果。同时,RecyclerView 也支持分页加载和多种布局方式,能够满足不同场景下的需求。

实现侧滑菜单

下面我们来看一下如何在 RecyclerView 中实现侧滑菜单。首先,我们需要在 RecyclerView 的 Adapter 中实现侧滑菜单的效果。具体实现方式如下:

1. 在 Adapter 中添加 ViewHolder

我们需要在 Adapter 中添加一个 ViewHolder 来显示侧滑菜单。在这个 ViewHolder 中,我们需要添加一个布局文件,用来显示菜单内容。

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView tvContent;
    public LinearLayout llMenu;

    public MyViewHolder(View itemView) {
        super(itemView);
        tvContent = itemView.findViewById(R.id.tv_content);
        llMenu = itemView.findViewById(R.id.ll_menu);
    }
}

2. 在 ViewHolder 中实现侧滑菜单的动画效果

在 ViewHolder 中,我们需要实现侧滑菜单的动画效果。具体实现方式如下:

public class MyViewHolder extends RecyclerView.ViewHolder {
    private static final int MENU_WIDTH = 200;

    private boolean isOpen;
    private float lastX;

    public TextView tvContent;
    public LinearLayout llMenu;

    public MyViewHolder(View itemView) {
        super(itemView);
        tvContent = itemView.findViewById(R.id.tv_content);
        llMenu = itemView.findViewById(R.id.ll_menu);

        itemView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        lastX = event.getRawX();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        float deltaX = event.getRawX() - lastX;
                        if (isOpen) {
                            deltaX -= MENU_WIDTH;
                        }
                        if (deltaX > 0) {
                            llMenu.setTranslationX(deltaX);
                            return true;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (isOpen) {
                            if (llMenu.getTranslationX() < MENU_WIDTH / 2) {
                                closeMenu();
                            } else {
                                openMenu();
                            }
                        } else {
                            if (llMenu.getTranslationX() > -MENU_WIDTH / 2) {
                                closeMenu();
                            } else {
                                openMenu();
                            }
                        }
                        break;
                }
                return false;
            }
        });
    }

    private void openMenu() {
        isOpen = true;
        llMenu.animate().translationX(0).start();
    }

    private void closeMenu() {
        isOpen = false;
        llMenu.animate().translationX(-MENU_WIDTH).start();
    }
}

在这个 ViewHolder 中,我们添加了一个 OnTouchListener 来监听用户的触摸事件。当用户滑动列表项时,我们根据滑动的距离来实现侧滑菜单的动画效果。当用户松手时,我们根据菜单的位置来判断菜单是应该打开还是关闭。

3. 在 Adapter 中实现菜单的点击事件

在 Adapter 中,我们需要实现菜单的点击事件。具体实现方式如下:

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    private List<String> mData;

    public MyAdapter(List<String> data) {
        mData = data;
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tvContent.setText(mData.get(position));
        holder.llMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理菜单的点击事件
            }
        });
    }

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

在这个 Adapter 中,我们在 onBindViewHolder 方法中添加了一个菜单的点击事件。当用户点击菜单时,我们可以在这个方法中处理相应的逻辑。

交互效果

除了侧滑菜单,RecyclerView 还支持多种交互效果。下面我们来看一下如何实现 RecyclerView 中的滑动删除效果。具体实现方式如下:

1. 在 Adapter 中添加 ViewHolder

我们需要在 Adapter 中添加一个 ViewHolder 来显示删除按钮。具体实现方式与侧滑菜单类似。

public class MyViewHolder extends RecyclerView.ViewHolder {
    private static final int MENU_WIDTH = 200;

    private boolean isOpen;
    private float lastX;

    public TextView tvContent;
    public LinearLayout llMenu;
    public LinearLayout llDelete;

    public MyViewHolder(View itemView) {
        super(itemView);
        tvContent = itemView.findViewById(R.id.tv_content);
        llMenu = itemView.findViewById(R.id.ll_menu);
        llDelete = itemView.findViewById(R.id.ll_delete);

        itemView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // ...
            }
        });

        llDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理删除按钮的点击事件
            }
        });
    }

    // ...
}

2. 在 Adapter 中实现删除操作

在 Adapter 中,我们需要实现删除操作。具体实现方式如下:

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    private List<String> mData;

    public MyAdapter(List<String> data) {
        mData = data;
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tvContent.setText(mData.get(position));

        holder.llDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = holder.getAdapterPosition();
                mData.remove(pos);
                notifyItemRemoved(pos);
            }
        });
    }

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

在这个 Adapter 中,我们在 onBindViewHolder 方法中添加了一个删除按钮的点击事件。当用户点击删除按钮时,我们可以在这个方法中处理相应的逻辑。同时,我们还需要调用 notifyItemRemoved 方法来更新列表的显示。

示例代码

下面是一个完整的示例代码,包含了 RecyclerView 中的侧滑菜单和滑动删除效果。

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private MyAdapter mAdapter;

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

        mRecyclerView = findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new MyAdapter(Arrays.asList("item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8"));
        mRecyclerView.setAdapter(mAdapter);
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        private static final int MENU_WIDTH = 200;

        private boolean isOpen;
        private float lastX;

        public TextView tvContent;
        public LinearLayout llMenu;
        public LinearLayout llDelete;

        public MyViewHolder(View itemView) {
            super(itemView);
            tvContent = itemView.findViewById(R.id.tv_content);
            llMenu = itemView.findViewById(R.id.ll_menu);
            llDelete = itemView.findViewById(R.id.ll_delete);

            itemView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            lastX = event.getRawX();
                            break;
                        case MotionEvent.ACTION_MOVE:
                            float deltaX = event.getRawX() - lastX;
                            if (isOpen) {
                                deltaX -= MENU_WIDTH;
                            }
                            if (deltaX > 0) {
                                llMenu.setTranslationX(deltaX);
                                return true;
                            }
                            break;
                        case MotionEvent.ACTION_UP:
                            if (isOpen) {
                                if (llMenu.getTranslationX() < MENU_WIDTH / 2) {
                                    closeMenu();
                                } else {
                                    openMenu();
                                }
                            } else {
                                if (llMenu.getTranslationX() > -MENU_WIDTH / 2) {
                                    closeMenu();
                                } else {
                                    openMenu();
                                }
                            }
                            break;
                    }
                    return false;
                }
            });

            llDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int pos = getAdapterPosition();
                    mAdapter.mData.remove(pos);
                    mAdapter.notifyItemRemoved(pos);
                }
            });
        }

        private void openMenu() {
            isOpen = true;
            llMenu.animate().translationX(0).start();
        }

        private void closeMenu() {
            isOpen = false;
            llMenu.animate().translationX(-MENU_WIDTH).start();
        }
    }

    public static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
        private List<String> mData;

        public MyAdapter(List<String> data) {
            mData = data;
        }

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

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.tvContent.setText(mData.get(position));
        }

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

总结

在 Material Design 中,RecyclerView 提供了一种简单的方式来实现侧滑菜单及交互效果。通过本文的介绍,我们可以学习到如何在 RecyclerView 中实现侧滑菜单和滑动删除效果。同时,我们也可以了解到 RecyclerView 的一些基本用法,为我们在开发移动应用时提供一些帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65bdf2c0add4f0e0ff78ca93