挑戰練習8.8 RecyclerView ViewType
阿新 • • 發佈:2018-11-03
請在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.執行效果: