1. 程式人生 > >挑戰練習8.8 RecyclerView ViewType

挑戰練習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.執行效果: