美文网首页常用控件Android
RecyclerView多布局与Item点击事件

RecyclerView多布局与Item点击事件

作者: 小胡闹 | 来源:发表于2016-05-12 22:25 被阅读9378次

    RecyclerView真的是太强大太强大的,没听过这个view 的可以自行google一下;
    本文将介绍RecyclerView的多布局;

    多布局的实现

    布局

    多布局是指一个不同的item用不同的layout显示。
    我们的主页面里面就放RecyclerView

      <android.support.v7.widget.RecyclerView
            android:id="@+id/recylerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    

    既然是要实现多布局,那么我们就写两个布局吧,一个item_normal,值包含一个 TextView

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="?listPreferredItemHeight"
        android:background="?selectableItemBackground"
        android:clickable="true"
        android:gravity="center"
        android:orientation="vertical"
        android:id="@+id/root_view"
        android:padding="10dp">
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp" />
    </LinearLayout>
    

    另外一个布局,放一个TextView和一个CheckBox;

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/root_view"
        android:layout_width="match_parent"
        android:layout_height="?listPreferredItemHeight"
        android:background="?selectableItemBackground"
        android:clickable="true"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="10dp">
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="hunao"
            android:textSize="18sp" />
    
        <CheckBox
            android:id="@+id/cb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true" />
    
    </LinearLayout>
    

    Adapter

    布局和item有了,那就要写Adapter了;
    自定义Adapter继承RecyclerView.Adapter<RecyclerView.ViewHolder>,复写需要复写的方法,我们来看一个这个方法,传进来的一个int类型的参数viewType,其实这个就相当于不同item的标记吧,我们可以根据这个值,给item选择不同的标记;

     @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          
        }
    

    那这个标记是从哪里来的呢?这个好办,RecyclerView.Adapter有一个方法getItemViewType(),返回值是int类;这个方法就是返回item布局类型标记的方法。

        private static final int NORMAL_TYPE = 0;
        private static final int CHECK_TYPE = 1;
    
        @Override
        public int getItemViewType(int position) {
            if (position % 4 == 0) {
                return CHECK_TYPE;
            }
            return NORMAL_TYPE;
        }
    

    如果position%4==0就返回NORMAL_TYPE,否则就返回CHECK_TYPE;然后我们就可以根据比较选择不同的布局了;

     @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == NORMAL_TYPE) {
                return new NormalHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_normal, parent, false));
            } else
                return new CheckHoldr(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_check, parent, false));
        }
    

    然后我们创建来数据就好了;
    给MyAdapter一个构造方法,传进来数据

    
        private List<String> datas;
    
        public MyAdapter(List<String> datas) {
            this.datas = datas;
        }
    

    每一个布局都要写一个ViewHolder

     class NormalHolder extends RecyclerView.ViewHolder  {
    
            TextView tv_name;
            LinearLayout rootView;
    
            public NormalHolder(View itemView) {
                super(itemView);
                tv_name = (TextView) itemView.findViewById(R.id.tv_name);
                rootView = (LinearLayout) itemView.findViewById(R.id.root_view);
            }
    
        class CheckHoldr extends NormalHolder {
            public CheckHoldr(View itemView) {
                super(itemView);
            }
        }
    

    这样,就可以给RecyclerView设置Adapter了

     private void initData() {
            datas = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                datas.add("hunao " + i);
            }
        }
    
        private void initView() {
            recylerView = (RecyclerView) findViewById(R.id.recylerview);
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recylerView.setLayoutManager(layoutManager);
            MyAdapter adapter = new MyAdapter(datas);
            recylerView.setAdapter(adapter);
        }
    
    Paste_Image.png

    Item点击事件

    RecyclerView并没有给我们封装item点击事件,那我们就自己动手吧
    我们需要在Adapter里面暴露出去一个借口,这样的,定义了一个OnItemClickListener借口,并且给了set方法,然后我们只要处理回调就可以了

       private OnItemClickListener clickListener;
    
        public void setClickListener(OnItemClickListener clickListener) {
            this.clickListener = clickListener;
        }
    
        public static interface OnItemClickListener {
            void onClick(View view, int position);
        }
    
    

    给我们的ViewHolder实现View.OnClickListener,然后重写onClick()方法,当OnItemClickListener监听器不为空的时候,就回调出去

     class NormalHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    
            TextView tv_name;
            LinearLayout rootView;
    
            public NormalHolder(View itemView) {
                super(itemView);
                tv_name = (TextView) itemView.findViewById(R.id.tv_name);
                rootView = (LinearLayout) itemView.findViewById(R.id.root_view);
                rootView.setOnClickListener(this);
            }
    
            @Override
            public void onClick(View v) {
                if (clickListener != null) {
                    clickListener.onClick(itemView, getAdapterPosition());
                }
            }
        }
    
        class CheckHoldr extends NormalHolder {
            public CheckHoldr(View itemView) {
                super(itemView);
            }
        }
    

    最后只要在Adapter上设置我们的监听器就可以了

     adapter.setClickListener(new MyAdapter.OnItemClickListener() {
                boolean flag = false;
                @Override
                public void onClick(View view, int position) {
                    TextView tvName = (TextView) view.findViewById(R.id.tv_name);
                    String name = flag ? "hunao" : "china";
                    tvName.setText(name + position);
                    flag = !flag;
                }
            });
    
    

    完整代码

    Activity
    package com.hugo.recylerviewdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        private RecyclerView recylerView;
        private List<String> datas;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initData();
            initView();
        }
    
        private void initData() {
            datas = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                datas.add("hunao " + i);
            }
        }
    
        private void initView() {
            recylerView = (RecyclerView) findViewById(R.id.recylerview);
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recylerView.setLayoutManager(layoutManager);
            MyAdapter adapter = new MyAdapter(datas);
            recylerView.setAdapter(adapter);
            adapter.setClickListener(new MyAdapter.OnItemClickListener() {
                boolean flag = false;
                @Override
                public void onClick(View view, int position) {
                    TextView tvName = (TextView) view.findViewById(R.id.tv_name);
                    String name = flag ? "hunao" : "china";
                    tvName.setText(name + position);
                    flag = !flag;
                }
            });
    
        }
    }
    
    
    MyAdapter
    package com.hugo.recylerviewdemo;
    
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import java.util.List;
    
    /**
     * @auther Hugo
     * Created on 2016/5/12 20:29.
     */
    public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private static final int NORMAL_TYPE = 0;
        private static final int CHECK_TYPE = 1;
    
        @Override
        public int getItemViewType(int position) {
            if (position % 4 == 0) {
                return CHECK_TYPE;
            }
            return NORMAL_TYPE;
        }
    
        private List<String> datas;
    
        public MyAdapter(List<String> datas) {
            this.datas = datas;
        }
    
        private OnItemClickListener clickListener;
    
        public void setClickListener(OnItemClickListener clickListener) {
            this.clickListener = clickListener;
        }
    
        public static interface OnItemClickListener {
            void onClick(View view, int position);
        }
    
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == NORMAL_TYPE) {
                return new NormalHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_normal, parent, false));
            } else
                return new CheckHoldr(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_check, parent, false));
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof NormalHolder) {
                ((NormalHolder) holder).tv_name.setText(datas.get(position));
            } else {
                ((CheckHoldr) holder).tv_name.setText(datas.get(position));
            }
        }
    
        @Override
        public int getItemCount() {
            return datas.size();
        }
    
        class NormalHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    
            TextView tv_name;
            LinearLayout rootView;
    
            public NormalHolder(View itemView) {
                super(itemView);
                tv_name = (TextView) itemView.findViewById(R.id.tv_name);
                rootView = (LinearLayout) itemView.findViewById(R.id.root_view);
                rootView.setOnClickListener(this);
            }
    
            @Override
            public void onClick(View v) {
                if (clickListener != null) {
                    clickListener.onClick(itemView, getAdapterPosition());
                }
            }
        }
    
        class CheckHoldr extends NormalHolder {
            public CheckHoldr(View itemView) {
                super(itemView);
            }
        }
    }
    
    

    相关文章

      网友评论

      • LucasJin:大佬,这么写咋有错啊:

        Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
        at com.ouman.sia.adapters.Main2RecyclerViewAdapter.onBindViewHolder(Main2RecyclerViewAdapter.java:66)


        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == NORMAL_TYPE) {
        return new NormalHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_icon, parent, false));
        } else
        return new CheckHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_icon_bages, parent, false));
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof NormalHolder) {
        ((NormalHolder) holder).tv_name.setText(data.get(position).getSection());
        ((NormalHolder) holder).iv_icon.setImageResource(data.get(position).getIconId());

        } else {
        ((CheckHolder) holder).tv_name.setText(data.get(position).getSection());
        ((CheckHolder) holder).iv_icon.setImageResource(data.get(position).getIconId());
        }
        }
      • LiKaiRabbit:导入你的MyAdapter,然后设置监听,没有用啊
        LiKaiRabbit:是我的问题,在fragment里面必须在子空间里添加上android:focusable="false"才能奏效,不好意思
      • 锕鎖:可以
      • 冰冰的冻结:getAdapterPosition() 这方法有方法详情吗
        小胡闹:@冰冰的冻结 它是RecyclerView.ViewHolder的方法,所以你要继承RecyclerView.ViewHolder才有这个方法
        冰冰的冻结:@小胡闹 我写的时候好没有这个方法啊
        小胡闹:@冰冰的冻结 他是ViewHolder里面的方法,可以直接用
      • 一个正在成为码农的人:有完整源码吗?
        小胡闹:@一个正在成为码农的人 不好意思,写的demo,没有存

      本文标题:RecyclerView多布局与Item点击事件

      本文链接:https://www.haomeiwen.com/subject/szpprttx.html