• 为RecyclerView添加item的点击事件


    RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一下观察者模式。

    其实在 这篇文章  中已经提到如何实现,但是里面有很多不规范的地方,而且没有完整的代码。

    最终目的

    模拟ListView的setOnItemClickListener()方法,调用者只须调用类似于setOnItemClickListener的东西就能获得被点击item的相关数据。

    原理

    为RecyclerView的每个子item设置setOnClickListener,然后在onClick中再调用一次对外封装的接口,将这个事件传递给外面的调用者。而“为RecyclerView的每个子item设置setOnClickListener”在Adapter中设置。其实直接在onClick中也能完全处理item的点击事件,但是这样会破坏代码的逻辑。

    步骤

    adapter中

    自定义一个继承自RecyclerView.Adapter的MyAdapter。

    1.在MyAdapter中定义如下接口,模拟ListView的OnItemClickListener:

      //define interface
        public static interface OnItemClickListener {
            void onItemClick(View view , int position);
        }

    声明一个这个接口的变量

        private OnItemClickListener mOnItemClickListener = null;

    在onCreateViewHolder()中为每个item添加点击事件

     @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
            ViewHolder vh = new ViewHolder(view);
            //将创建的View注册点击事件
            view.setOnClickListener(this);
            return vh;
        }

    将点击事件转移给外面的调用者:

        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                //注意这里使用getTag方法获取position
                mOnItemClickListener.onItemClick(v,(int)v.getTag());
            }
        }

    注意上面调用接口的onItemClick()中的v.getTag()方法,这需要在onBindViewHolder()方法中设置和item的position

        @Override
        public void onBindViewHolder(ViewHolder viewHolder,  int position) {
            viewHolder.mTextView.setText(datas[position]);
            //将position保存在itemView的Tag中,以便点击时进行获取
            viewHolder.itemView.setTag(position);
        }

    最后暴露给外面的调用者,定义一个设置Listener的方法():

        public void setOnItemClickListener(OnItemClickListener listener) {
            this.mOnItemClickListener = listener;
        }

    以上所有步骤都发生在自定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。

    在Activity中使用

            mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
            //创建默认的线性LayoutManager
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);
            //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
            mRecyclerView.setHasFixedSize(true);
            //创建并设置Adapter
            mAdapter = new MyAdapter(data);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.setOnItemClickListener(new OnItemClickListener(){
                @Override    
                public void onItemClick(View view , int position){
                    Toast.makeText(MainActivity.this, data[position], 600).show();
                }
            });

    完整代码

    MyAdapter.java

    package com.example.recyclerviewdemo;
     
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
     
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
        private  String[]  datas;
        public MyAdapter(String[] datas) {
            this.datas = datas;
        }
        private OnItemClickListener mOnItemClickListener = null;
        
        //define interface
        public static interface OnItemClickListener {
            void onItemClick(View view , int position);
        }
        
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
            ViewHolder vh = new ViewHolder(view);
            //将创建的View注册点击事件
            view.setOnClickListener(this);
            return vh;
        }
        
        @Override
        public void onBindViewHolder(ViewHolder viewHolder,  int position) {
            viewHolder.mTextView.setText(datas[position]);
            //将position保存在itemView的Tag中,以便点击时进行获取
            viewHolder.itemView.setTag(position);
        }
     
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                //注意这里使用getTag方法获取position
                mOnItemClickListener.onItemClick(v,(int)v.getTag());
            }
        }
     
        public void setOnItemClickListener(OnItemClickListener listener) {
            this.mOnItemClickListener = listener;
        }
     
        
        //获取数据的数量
        @Override
        public int getItemCount() {
            return datas.length;
        }
        //自定义的ViewHolder,持有每个Item的的所有界面元素
        public static class ViewHolder extends RecyclerView.ViewHolder {
            public TextView mTextView;
            public ViewHolder(View view){
            super(view);
                mTextView = (TextView) view.findViewById(R.id.text);
            }
        }
    }

    item.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="50dip"
       >
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </RelativeLayout>

    MainActivity.java

    package com.example.recyclerviewdemo;
     
    import com.example.recyclerviewdemo.MyAdapter.OnItemClickListener;
     
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Toast;
     
    public class MainActivity extends ActionBarActivity {
        private RecyclerView mRecyclerView;
        private LinearLayoutManager mLayoutManager;
        private MyAdapter mAdapter;
        private String[] data= new String[] {"aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb","aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb"  };
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
            //创建默认的线性LayoutManager
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);
            //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
            mRecyclerView.setHasFixedSize(true);
            //创建并设置Adapter
            mAdapter = new MyAdapter(data);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.setOnItemClickListener(new OnItemClickListener(){
                @Override    
                public void onItemClick(View view , int position){
                    Toast.makeText(MainActivity.this, data[position], 600).show();
                }
            });
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
         
     
    }

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/my_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"/>
    </RelativeLayout>

    总结

    在ListView中我们是调用ListView的setOnItemClickListener:

            mListView.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                    
                        ...           
                   
                }
            });

    而在我们这里是调用mAdapter的setOnItemClickListener。

    RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一下观察者模式。

    其实在 这篇文章  中已经提到如何实现,但是里面有很多不规范的地方,而且没有完整的代码。

    最终目的

    模拟ListView的setOnItemClickListener()方法,调用者只须调用类似于setOnItemClickListener的东西就能获得被点击item的相关数据。

    原理

    为RecyclerView的每个子item设置setOnClickListener,然后在onClick中再调用一次对外封装的接口,将这个事件传递给外面的调用者。而“为RecyclerView的每个子item设置setOnClickListener”在Adapter中设置。其实直接在onClick中也能完全处理item的点击事件,但是这样会破坏代码的逻辑。

    步骤

    adapter中

    自定义一个继承自RecyclerView.Adapter的MyAdapter。

    1.在MyAdapter中定义如下接口,模拟ListView的OnItemClickListener:

        //define interface
        public static interface OnItemClickListener {
            void onItemClick(View view , int position);
        }

    声明一个这个接口的变量

        private OnItemClickListener mOnItemClickListener = null;

    在onCreateViewHolder()中为每个item添加点击事件

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
            ViewHolder vh = new ViewHolder(view);
            //将创建的View注册点击事件
            view.setOnClickListener(this);
            return vh;
        }

    将点击事件转移给外面的调用者:

       @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                //注意这里使用getTag方法获取position
                mOnItemClickListener.onItemClick(v,(int)v.getTag());
            }
        }

    注意上面调用接口的onItemClick()中的v.getTag()方法,这需要在onBindViewHolder()方法中设置和item的position

        @Override
        public void onBindViewHolder(ViewHolder viewHolder,  int position) {
            viewHolder.mTextView.setText(datas[position]);
            //将position保存在itemView的Tag中,以便点击时进行获取
            viewHolder.itemView.setTag(position);
        }

    最后暴露给外面的调用者,定义一个设置Listener的方法():

        public void setOnItemClickListener(OnItemClickListener listener) {
            this.mOnItemClickListener = listener;
        }

    以上所有步骤都发生在自定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。

    在Activity中使用

            mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
            //创建默认的线性LayoutManager
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);
            //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
            mRecyclerView.setHasFixedSize(true);
            //创建并设置Adapter
            mAdapter = new MyAdapter(data);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.setOnItemClickListener(new OnItemClickListener(){
                @Override    
                public void onItemClick(View view , int position){
                    Toast.makeText(MainActivity.this, data[position], 600).show();
                }
            });

    完整代码

    MyAdapter.java

    package com.example.recyclerviewdemo;
     
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
     
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
        private  String[]  datas;
        public MyAdapter(String[] datas) {
            this.datas = datas;
        }
        private OnItemClickListener mOnItemClickListener = null;
        
        //define interface
        public static interface OnItemClickListener {
            void onItemClick(View view , int position);
        }
        
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
            ViewHolder vh = new ViewHolder(view);
            //将创建的View注册点击事件
            view.setOnClickListener(this);
            return vh;
        }
        
        @Override
        public void onBindViewHolder(ViewHolder viewHolder,  int position) {
            viewHolder.mTextView.setText(datas[position]);
            //将position保存在itemView的Tag中,以便点击时进行获取
            viewHolder.itemView.setTag(position);
        }
     
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                //注意这里使用getTag方法获取position
                mOnItemClickListener.onItemClick(v,(int)v.getTag());
            }
        }
     
        public void setOnItemClickListener(OnItemClickListener listener) {
            this.mOnItemClickListener = listener;
        }
     
        
        //获取数据的数量
        @Override
        public int getItemCount() {
            return datas.length;
        }
        //自定义的ViewHolder,持有每个Item的的所有界面元素
        public static class ViewHolder extends RecyclerView.ViewHolder {
            public TextView mTextView;
            public ViewHolder(View view){
            super(view);
                mTextView = (TextView) view.findViewById(R.id.text);
            }
        }
    }

    item.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="50dip"
       >
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </RelativeLayout>

    MainActivity.java

    package com.example.recyclerviewdemo;
     
    import com.example.recyclerviewdemo.MyAdapter.OnItemClickListener;
     
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Toast;
     
    public class MainActivity extends ActionBarActivity {
        private RecyclerView mRecyclerView;
        private LinearLayoutManager mLayoutManager;
        private MyAdapter mAdapter;
        private String[] data= new String[] {"aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb","aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb"  };
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
            //创建默认的线性LayoutManager
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);
            //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
            mRecyclerView.setHasFixedSize(true);
            //创建并设置Adapter
            mAdapter = new MyAdapter(data);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.setOnItemClickListener(new OnItemClickListener(){
                @Override    
                public void onItemClick(View view , int position){
                    Toast.makeText(MainActivity.this, data[position], 600).show();
                }
            });
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
         
     
    }

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/my_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"/>
    </RelativeLayout>

    总结

    在ListView中我们是调用ListView的setOnItemClickListener:

            mListView.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                    
                        ...           
                   
                }
            });

    而在我们这里是调用mAdapter的setOnItemClickListener。

  • 相关阅读:
    OO第二单元架构随笔
    OO第二单元小结
    OO第一单元小结
    OO第四单元总结
    oo第三单元总结
    OO第二单元总结
    OO第一单元总结
    OO第四单元及课程总结
    OO第三单元总结
    OO第二单元总结
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7187548.html
Copyright © 2020-2023  润新知