zoukankan      html  css  js  c++  java
  • OnItemClickListener接口回调实现RecyclerView点击事件

    1、技术概述

    使用ReclclerView列出账单分类,使用OnItemClickListener接口回调的方法实现在RecyclerView.Adapter外实现对RecyclerView的子项的点击交互事件。技术难点在于在适配器中定义接口,在具体引用的Activity中调用接口具体实现。

    2、技术详述

    (1)要使用RecyclerView这个控件,首先得在项目的build.gradle中添加相应的依赖库。

    • 打开app/build.gradle文件,在dependencies闭包中添加以下内容:
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support:recyclerview-v7:28.0.0'
        testCompile 'junit:junit:4.12'
    }
    
    • 添加完成后记得点击Sync Now进行库的同步。

    (2)安装完依赖后,我们到布局文件中引入ReclclerView。外面包裹的容器是要RelativeLayout或者LinearLayout看你是要竖着显示每个Item还是横着显示。

    • RelativeLayout是列表式的竖着显示:
       ······
    <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/reclcler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    
    </RelativeLayout>
       ······
    
    • 具体效果图:

    • LinearLayout为横向显示,加上GridLayout可以使Item呈网格式布局。
       ······
    <GridLayout
                android:id="@+id/viewpager_item"
                android:layout_width="match_parent"
                android:layout_height="130dp">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
    
                    <android.support.v7.widget.RecyclerView
                        android:id="@+id/category_recycle_view"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"/>
    
                </LinearLayout>
    </GridLayout>
       ······
    
    • 具体效果图:

    (3)在layout文件中引入ReclclerView后,还需要增加一个xml布局文件,用以定义每个Item要显示的内容。具体如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/cardview_light_background">
    
            <TextView
                android:id="@+id/category_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:textColor="@color/cardview_dark_background" />
    
        </RelativeLayout>
    </LinearLayout>
    
    • 这边仅定义了一个TextView用于显示账单分类的名称,大家可以根据需求自行修改。

    (4)准备完布局文件,我们需要为RecyclerView准备一个适配器,新建一个类CategoryAdapter,让这个适配器继承自ReclclewView.Adapter,并将泛型指定为CategoeyAdapter.ViewHolder。

    • 在《第一行代码》中RecyclerView中的点击事件是直接在适配器中实现的,这很显然不能满足我们的要求,所以我们在适配器中定义OnItemClickListener接口,然后在要引用适配器的Activity中具体实现该接口,以达到我们所要的RecyclerView的点击交互效果。具体适配器代码如下:
    public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {
        private List<Category> mCategoryList;
    
        //定义OnItemClickListener接口
        public interface OnItemClickListener {
            void onClick(int position);
        }
    
        public OnItemClickListener listener;
    
        public void setOnItemClickListener(OnItemClickListener listener) {
            this.listener = listener;
        }
    
        static class ViewHolder extends RecyclerView.ViewHolder {
            TextView categoryName;
    
            public ViewHolder(View view) {
                super(view);
                categoryName = (TextView) view.findViewById(R.id.category_name);
            }
        }
    
        public CategoryAdapter(List<Category> mCList) {
            mCategoryList = mCList;
        }
    
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.category_item, parent, false);
            return new ViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            Category category = mCategoryList.get(position);
            holder.categoryName.setText(category.getCategory_name());
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        listener.onClick(position);
                    }
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return mCategoryList.size();
        }
    
    }
    

    (5)最后,我们在具体的Activity中引入适配器。具体代码及释义如下:

    public class CategoryEditActivity extends AppCompatActivity implements View.OnClickListener {
        ······
        public CategoryChooseAdapter categoryChooseAdapter;
        public RecyclerView recycleView;
        ······
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        ······
        recycleView = (RecyclerView) findViewById(R.id.reclcler_view);
    
        //初始化数据,装入ReclclerView中
        initCategory();
        }
        
        //具体实现RecyclerView的Item点击事件
        public void setCategoryChooseAdapter () {
            //在这边实现具体的Item交互事件,点击事件交互的内容可以自行定义
            categoryChooseAdapter.setOnItemClickListener(new CategoryChooseAdapter.OnItemClickListener() {
                @Override
                public void onClick(int position) {
                    ······
                    //这边我使用MaterialDialog来实现点击一个Item后,出现对话框用以修改分类信息
                    new MaterialDialog.Builder(CategoryEditActivity.this)
                            .title("修改分类")
                            .canceledOnTouchOutside(false)
                            .input(category_name1, "", new MaterialDialog.InputCallback() {
                                @Override
                                public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
    
                                }
                            })
                            .positiveText("确认修改")
                            .negativeText("取消")
                            .neutralText("删除该分类")
                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                @Override
                                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                    //修改分类
                                    ······
                                    Toast.makeText(CategoryEditActivity.this, "修改成功!", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .onNeutral(new MaterialDialog.SingleButtonCallback() {
                                @Override
                                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                    ······
                                    //删除分类
                                    Toast.makeText(CategoryEditActivity.this, "该分类已成功删除!", Toast.LENGTH_SHORT).show();
                                
                            })
                            .onNegative(new MaterialDialog.SingleButtonCallback() {
                                @Override
                                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                    //取消
                                    dialog.dismiss();
                                    dialog = null;
                                }
                            })
                            .show();
                }
            });
        }
    
        private void initCategory() {
            CategoryDAO categoryDAO = new CategoryDAOImpl();
            categoryList = categoryDAO.listCategory();
            //从数据库按需取出分类名称,装入categoryList中
            ······
            categoryChooseAdapter = new CategoryChooseAdapter(categoryList);  //将数据装入RecycerView适配器中
            categoryChooseAdapter.notifyItemRangeChanged(0, categoryList.size());  //当新添或者删除某个Item时,能够即时刷新数据
            recycleView.setAdapter(categoryChooseAdapter); //完成适配器设置
    
            setCategoryChooseAdapter();  //实现每一个Item点击事件
        }
    }
    
    • 具体效果图:

    3、技术使用中遇到的问题和解决过程

     RecyclerView并没有提供类似于setOnItemClickListener这样的注册监听器方法,而是需要我们给子项具体的View去注册点击事件。而在《第一行代码》中实现RecyclerView点击事件是在Adapter中的onCreateViewHolder()方法中注册点击事件,使用这种方法的话,当我们想要的点击事件复杂一点或者需要使用具体引入的Activity中的一些数据时,就没办法满足。所以开始找寻能够在适配器之外实现点击事件的方法。
     经过一番搜寻,发现可以通过接口回调的方式实现外部定义点击事件。通过在RecyclerView的适配器中定义OnItemClickListener接口,再在Activity中调用接口,具体实现以解决自定义点击子项交互的问题。
     使用RecyclerView时如果修改了某项子项页面数据却没有即时刷新的话,可调用RecyclerView中的notifyItemRangeChanged()方法,再重新设置适配器setAdapter(),来实现数据的实时更新。

        ······
        categoryChooseAdapter = new CategoryChooseAdapter(categoryList);  //将数据装入RecycerView适配器中
        categoryChooseAdapter.notifyItemRangeChanged(0, categoryList.size());  //当修改或者删除某个Item时,能够即时刷新数据
        recycleView.setAdapter(categoryChooseAdapter); //完成适配器设置
    

    4、总结

    《第一行代码》只是为你的Android开发打下一定的基础,对Android开发的一些基础知识进行较为详细的介绍。而要想做好Android开发,单单靠学完《第一行代码》还是不够的,还需要我们在实际开发时不断地去查找资料,学习更多的拓展知识。

    5、参考文献、参考博客

  • 相关阅读:
    oo第四次作业总结
    oo第三次博客总结
    oo第二次博客总结
    oo第一次博客总结
    leetcode155-最小栈
    leetcode141-环形链表
    leetcode278-第一个错误的版本
    leetcode118-杨辉三角
    LeetCode21-合并两个有序列表
    LeetCode27-移除元素
  • 原文地址:https://www.cnblogs.com/zytblog/p/13179905.html
Copyright © 2011-2022 走看看