挑战练习8.8 RecyclerView ViewType

  请在RecyclerView中创建两类列表项:一般性crime,以及需警方介入的crime。要完成这个挑战,你需要用到RecyclerView.Adapter的视图类别功能(view type)。在Crime对象里,再添加一个mRequiresPolice实例变量,使用它并借助getItemViewType(int)方法,确定该加载哪个视图到CrimeAdapter。

  在onCreateViewHolder(ViewGroup,int)方法里,基于getItemViewType(int)方法返回的ViewType值,需要返回不同的ViewHolder。如果是一般性crime,就仍然使用原始布局;如果是需警方介入的crime,就使用一个带联系警方按钮的新布局。


1.题目要求两类列表项,如果是需警方介入的crime,就使用一个带联系警方按钮的新布局,因此添加一个新的xml布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 
 3 <LinearLayout
 4     xmlns:android="http://schemas.android.com/apk/res/android"
 5     android:layout_width="match_parent"
 6     android:layout_height="wrap_content"
 7     android:orientation="vertical"
 8     android:padding="8dp">
 9     <TextView
10         android:id="@+id/crime_title"
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content"
13         android:text="Crime Title"/>
14 
15     <TextView
16         android:id="@+id/crime_date"
17         android:layout_width="match_parent"
18         android:layout_height="wrap_content"
19         android:text="Crime Date"/>
20     <!--挑战练习:新增一个报警按钮-->
21     <Button
22         android:id="@+id/require_police"
23         android:layout_width="wrap_content"
24         android:layout_height="wrap_content"
25         android:text="call 110"
26         android:textAllCaps="false"/>
27 </LinearLayout>

2.在Crime对象里,再添加一个mRequiresPolice实例变量,并且为mRequiresPolice添加响应的getter和setter方法

 1 package com.bignerdranch.android.criminalintent.entity;
 2 
 3 import java.util.Date;
 4 import java.util.UUID;
 5 
 6 public class Crime {
 7     private UUID mId;
 8     private String mTitle;
 9     private Date mDate;
10     private boolean mSolved;
11     //题目要求的是否叫警察
12     private boolean mRequiresPolice;
13 
14     public Crime() {
15         this.mId = UUID.randomUUID();
16         this.mDate = new Date();
17     }
18 
19     public UUID getmId() {
20         return mId;
21     }
22 
23     public String getmTitle() {
24         return mTitle;
25     }
26 
27     public void setmTitle(String mTitle) {
28         this.mTitle = mTitle;
29     }
30 
31     public Date getmDate() {
32         return mDate;
33     }
34 
35     public void setmDate(Date mDate) {
36         this.mDate = mDate;
37     }
38 
39     public boolean ismSolved() {
40         return mSolved;
41     }
42 
43     public void setmSolved(boolean mSolved) {
44         this.mSolved = mSolved;
45     }
46 
47     public boolean ismRequiresPolice() {
48         return mRequiresPolice;
49     }
50 
51     public void setmRequiresPolice(boolean mRequiresPolice) {
52         this.mRequiresPolice = mRequiresPolice;
53     }
54 }

3.在CrimeLab中赋值,每10个就是需要警方介入的crime

 1 public  CrimeLab(Context context) {
 2         mCrimes = new ArrayList<>();
 3         for (int i = 0; i < 100; i++) {
 4             Crime crime = new Crime();
 5             crime.setmTitle("Crime #" + i);
 6             crime.setmSolved(i % 2 == 0);
 7             //每隔10个就是需警方介入的crime
 8             crime.setmRequiresPolice(i % 10 == 0);
 9             mCrimes.add(crime);
10         }
11     }

4.在原本CrimeHolder的基础下新增一个requirePoliceCrimeHolder内部类

 1  //定义一个新的requirePoliceCrimeHolder内部类一个CrimeHolder对应一行列表项,对应布局为 list_item_require_crime
 2     private class requirePoliceCrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
 3         private TextView mTitleTextView;
 4         private TextView mDateTextView;
 5         private Button mRequirePolice;
 6         private Crime mCrime;
 7 
 8         //只要收到一个crime,CrimeHolder就会刷新显示mTitleTextView和mDateTextView
 9         private void bind(Crime crime) {
10             mCrime = crime;
11             mTitleTextView.setText(mCrime.getmTitle());
12             mDateTextView.setText(mCrime.getmDate().toString());
13         }
14 
15         public requirePoliceCrimeHolder(LayoutInflater inflater,ViewGroup parent) {
16             //首先实例化 list_item_require_crime 布局然后传给super()即ViewHolder的构造方法*/
17             super(inflater.inflate(R.layout.list_item_crime,parent,false));
18 
19             mTitleTextView = (TextView)itemView.findViewById(R.id.crime_title);
20             mDateTextView = (TextView)itemView.findViewById(R.id.crime_date);
21             mRequirePolice = (Button)itemView.findViewById(R.id.require_police);
22             itemView.setOnClickListener(this);
23         }
24 
25         @Override
26         public void onClick(View v) {
27             Toast.makeText(getActivity(),"Require Police!",Toast.LENGTH_SHORT).show();
28         }
29     }

5.适配器CrimeAdapter,现在多了requirePoliceCrimeHolder,适配器就不能专门用泛型接收CrimeHolder了, 在onCreateViewHolder(ViewGroup,int)方法里,基于getItemViewType(int)方法返回的ViewType值,需要返回不同的ViewHolder。

 1  public class CrimeAdapter extends RecyclerView.Adapter {
 2         private List<Crime> mCrimes;
 3         public CrimeAdapter(List<Crime> crimes) {
 4             mCrimes = crimes;
 5         }
 6         //视图类别功能
 7         @Override
 8         public int getItemViewType(int position) {
 9             //真不报警
10             if(mCrimes.get(position).ismRequiresPolice()) {
11                 return 1;
12             }else{
13                 return 0;
14             }
15         }
16         @NonNull
17         @Override
18         public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
19             //先创建LayoutInflater
20             LayoutInflater layoutInflater=LayoutInflater.from(getActivity());
21 
22             //判断上面的i的值判断使用什么布局,即getItemViewType的返回值
23             if (i == 1)
24                 return new requirePoliceCrimeHolder(layoutInflater, viewGroup);
25             else
26                 return new CrimeHolder(layoutInflater, viewGroup);
27         }
28 
29         //需要绑定数据(上下滑动屏幕)时,就会读取当前位置并绑定
30         @Override
31         public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
32             if (holder instanceof CrimeHolder) {    //instance,如果左侧的对象是右侧类的实例,则返回true
33                 Crime crime = mCrimes.get(position);
34                 ((CrimeHolder)holder).bind(crime);
35             }else if (holder instanceof requirePoliceCrimeHolder){
36                 Crime crime = mCrimes.get(position);
37                 ((requirePoliceCrimeHolder)holder).bind(crime);
38             }
39         }
40 
41         @Override
42         public int getItemCount() {
43             return mCrimes.size();
44         }
45     }

6.运行效果:

 

 


 

posted @ 2018-11-03 20:42  杜王町上班族  阅读(1670)  评论(0编辑  收藏  举报