http://www.cnblogs.com/xfangs/
歡迎在本文下方評論,小方很需要鼓勵支持!!!
本系列教程僅供學習交流
前言
在上一篇文章中,我們實現了ViewPager的基本功能,按照計划,制作咱們的電子書閱讀app需要使用ViewPager插入兩頁視圖,一個用來顯示當前書架,一個用來展示不同的分類。這一節,我們將在被標記為find的頁面上實現分類選項。
涉及組件或框架:RecyclerView、Glide
首先·布局
同樣的,在這里,小方因為水平有限只能簡單介紹RecyclerView的基本使用方法,涉及到更深奧的操作部分,就無能為力了。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <android.support.v7.widget.RecyclerView 7 android:id="@+id/recyler_view_find_book" 8 android:layout_margin="8dp" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent"/> 11 12 </LinearLayout>
沒有復雜的步驟,我們只需要把RecyclerView加入到之前ViewPager的兩個布局之一中,就完成了整個列表布局。
當然,你也許會遇到一些意外。
這是說明我們還沒有引入RecyclerView這個庫,進入Design界面,從左邊的組件中找到RecyclerView,單擊,將會彈出選擇框。
在加入了庫之后,我們就能看到RecyclerView正確無誤的顯示在界面上了。
適配器
這次我們工作的主戰場在上一節提到的Fragment,也就是ViewPager的兩個頁面之一。
回顧一下代碼。
1 public static class FindBooksFragment extends Fragment { 2 3 public FindBooksFragment() { 4 } 5 6 @Override 7 public View onCreateView(final LayoutInflater inflater, ViewGroup container, 8 Bundle savedInstanceState) { 9 10 View rootView = inflater.inflate(R.layout.pager_book_find, container, false); 11 12 return rootView; 13 } 14 15 }
之前說了,ViewPager會在創建這個頁面的時候調用onCreateView這個函數,所以我們在這里進行初始化操作。
在這之前,我們需要先完成RecyclerView的適配器,同樣的,這里適配器起到將數據和頁面結合到一起的作用,具體地說,假設一個列表中的項目可以分為三類,我們就為這三類元素分別設計布局,然后將每一項的數據傳給適配器,適配器可以根據數據選擇對應的布局,然后把每一項顯示出來。
首先,新建一個類。
關於RecyclerView的適配器,網絡上已經有很多博客描述了, 隨意找一篇看的過去的文章,先大體了解一下。
。。。搜索時間。。。
了解過后,我們知道需要為列表項寫布局,這在前面也間接提到了。
那么,新建一個布局文件
book_find_item.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:id="@+id/bookFind_cardview" 5 android:layout_width="match_parent" 6 android:layout_height="wrap_content" 7 android:layout_margin="4dp" 8 android:foreground="?android:attr/selectableItemBackground" 9 android:clickable="true"> 10 11 <ImageView 12 android:id="@+id/bookFind_image" 13 android:layout_width="match_parent" 14 android:layout_height="150dp" 15 android:scaleType="centerCrop" 16 tools:src="@color/cardview_dark_background"/> 17 18 <TextView 19 android:id="@+id/bookFind_class" 20 android:layout_width="match_parent" 21 android:layout_height="match_parent" 22 android:background="#00000000" 23 android:textColor="#FFFFFF" 24 android:textStyle="normal|bold" 25 android:textSize="14sp" 26 android:gravity="center" 27 tools:text="123"/> 28 29 </android.support.v7.widget.CardView>
在這里,我們又使用了一個新的組件,CardView,它體現了安卓最新設計風格,恰到好處的圓角、逼真的陰影、點擊特效、等等,有多種屬性可供調整。
尤其要說的是上面代碼中加粗的字體,一個新的命名空間 tools ,在使用它之前,我們首先要在最外層的部件上聲明。
只要打出前面幾個字母,android studio 就會自動補全好。
tools 命名空間提供了測試的效果,以他為名號的屬性在程序運行期間是被忽略的,只供測試預覽使用,使得開發更加方便了。下圖就是我們預覽時得到的效果,
當程序運行起來時, 還會是如圖所示的樣子嗎?
(必然不是)
制作好了布局文件,我們就可以開始對適配器進行編寫了。
首先制作一個接口,用來獲取點擊事件。
1 private OnItemClickListener listener; 2 3 public void setOnItemClickListener(OnItemClickListener listener) { 4 this.listener = listener; 5 } 6 7 public interface OnItemClickListener { 8 void onItemClick(View view, int position); 9 void onItemLongClick(View view, int position); 10 }
然后在適配器的類中再新建一個類。
1 static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { 2 View tocView; 3 private TextView textview_bookFindClass; 4 private ImageView imageView; 5 private OnItemClickListener listener; 6 7 public ViewHolder(View itemView, OnItemClickListener l) { 8 super(itemView); 9 tocView = itemView; 10 textview_bookFindClass = (TextView) itemView.findViewById(R.id.bookFind_class); 11 imageView = (ImageView) itemView.findViewById(R.id.bookFind_image); 12 listener = l; 13 itemView.setOnClickListener(this); 14 itemView.setOnLongClickListener(this); 15 } 16 17 18 @Override 19 public void onClick(View v) { 20 if (listener != null) { 21 listener.onItemClick(v, getAdapterPosition()); 22 } 23 } 24 25 @Override 26 public boolean onLongClick(View v) { 27 if (listener != null) { 28 listener.onItemLongClick(v, getAdapterPosition()); 29 } 30 return false; 31 } 32 }
可能略顯復雜,這個類的作用是緩存列表項,具體比較低層的東西小方就不太清楚了,上網搜了搜,就不現學現賣了,歡迎有興趣的同學一起討論。
ViewHolder 類繼承自 RecyclerView.ViewHolder,為了實現點擊監聽,還要接入兩個接口,一個是單擊的接口,一個是長按的接口。
從構造函數開始一點一點理解,構造函數接收兩個參數,一個是每一項的View,一個是每一項的點擊監聽器。初始化組件之后,設置監聽器,按照之前設置的接口的設定,將View和位置傳給借口。
如果還不是很清楚,那么先將代碼復制過去,使用次數多了,自然就理解了。
然后,在AdapterBookFind這個類中,完成它的構造函數,這里是根據需要自行設定的,在這里我們需要將分類名稱傳給適配器,顯示在每一項上,所以傳送了一個字符串列表。你也可以根據自己的需要傳送想要傳送的數據。
1 private ArrayList<String> myCategory; 2 3 public AdapterBookFind(ArrayList<String> category) { 4 this.myCategory = category; 5 }
下面我們需要重寫一個函數,用來獲取一個ViewHolder的實例。
1 private Context context; 2 @Override 3 public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { 4 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.book_find_item, parent, false); 5 context = parent.getContext(); 6 final ViewHolder holder = new ViewHolder(view, listener); 7 8 return holder; 9 }
在這里,我們又聲明了一個叫做context的變量,並初始化,具體作用后面再表。
1 @Override 2 public int getItemCount() { 3 return myCategory.size(); 4 }
類似ViewPager的適配器一樣,我們同樣需要重寫取數目的函數,根據數據返回一個值。
馬上就到最后一步了,我們將要對列表的每一項設置不同的內容。
1 @Override 2 public void onBindViewHolder(final ViewHolder holder, int position) { 3 holder.textview_bookFindClass.setText(myCategory.get(position)); 4 5 switch (position) { 6 case 0: 7 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 8 break; 9 case 1: 10 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 11 break; 12 case 2: 13 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 14 break; 15 case 3: 16 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 17 break; 18 case 4: 19 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 20 break; 21 case 5: 22 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 23 break; 24 case 6: 25 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 26 break; 27 case 7: 28 Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView); 29 break; 30 default: 31 32 break; 33 } 34 holder.imageView.setColorFilter(Color.parseColor("#55555555")); 35 36 }
因為我們的布局文件中只有兩個組件能體現數據的內容,TextView和ImageView。
第三行是根據不同的位置選擇不同的字符串進行設置,沒有難度。
在說switch之前,我們先來看最后一行
holder.imageView.setColorFilter(Color.parseColor("#55555555"));
給imageView設置濾色,因為我想要在圖片之上顯示一個白色的文字,適當的使圖片變暗,能凸顯文字。
switch當然也能看得懂,但是出現了一個陌生的東西 Glide。
實際不難理解,這個switch的作用還是根據不同的位置選擇不同的文件進行顯示,我們當然可以使用ImageView自帶的方法來設置圖片,但是ImageView只能設置本地或者APK之中的圖片資源,對於網絡圖片或者諸多不支持的圖片類型(如GIF)就毫無辦法,不僅如此,當本地圖片較大時,還會不可避免的出現卡頓現象。
這時候Glide出現了,它能快速加載各種圖片,根據顯示大小自動對圖片進行壓縮,同樣一條語句,如果傳入圖片鏈接還能加載網絡圖片,並緩存。
Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imageView);
如上面代碼所示的一句話,就能加載APK資源中的一張圖片,這里我們只有圖標一個文件,所以將圖標文件傳給了imageView。
不過如果你只是把剛剛的代碼復制粘貼到你的工程,你的程序應該會報錯,顯示沒有找到Glide這個東西,這是因為Glide不是官方提供的,我們需要手動引入。
找到上面那個文件。
加入最后一行,選擇同步。
這樣,我們就引入了Glide。
整合
1 public static class FindBooksFragment extends Fragment { 2 3 public FindBooksFragment() { 4 } 5 6 private RecyclerView recyclerView; 7 private StaggeredGridLayoutManager staggeredGridLayoutManager; 8 private AdapterBookFind bookAdapterBookFind; 9 10 @Override 11 public View onCreateView(final LayoutInflater inflater, ViewGroup container, 12 Bundle savedInstanceState) { 13 14 final ArrayList<String> bookClass = new ArrayList<>(); 15 bookClass.add("//玄幻"); 16 bookClass.add("//武俠"); 17 bookClass.add("//都市"); 18 bookClass.add("//歷史"); 19 bookClass.add("//游戲"); 20 bookClass.add("//科幻"); 21 bookClass.add("//女生"); 22 bookClass.add("//所有"); 23 24 View rootView = inflater.inflate(R.layout.pager_book_find, container, false); 25 recyclerView = (RecyclerView) rootView.findViewById(R.id.recyler_view_find_book); 26 27 staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 28 recyclerView.setLayoutManager(staggeredGridLayoutManager); 29 bookAdapterBookFind = new AdapterBookFind(bookClass); 30 recyclerView.setAdapter(bookAdapterBookFind); 31 32 bookAdapterBookFind.setOnItemClickListener(new AdapterBookFind.OnItemClickListener() { 33 @Override 34 public void onItemClick(View view, int position) { 35 Log.e(TAG, "onItemClick: 111" ); 36 } 37 38 @Override 39 public void onItemLongClick(View view, int position) { 40 Log.e(TAG, "onItemLongClick: 222" ); 41 } 42 }); 43 44 return rootView; 45 } 46 47 private static final String TAG = "FindBooksFragment"; 48 49 }
首先初始化我們的字符串列表。StaggeredGridLayoutManager是我們列表的布局管理器,安卓提供了三種布局管理器,用來實現不同的列表效果,多行列表,瀑布流列表,不同的滑動方向都可以進行設置,大家可以百度其他的布局管理器。
所以在27-30行,我們分別為RecyclerView設置了列表管理器和適配器,32行開始,為適配器設置點擊監聽器,咱們暫時不設置功能,使用log工具將其輸出在Android Monitor(log語句有快捷鍵)。
效果
運行程序,你將見到
我們又完成了新的一節,現在可以嘗試更換不同的圖片,嘗試使用網絡圖片(不要忘記加入網絡訪問權限)。
未完待續...下一篇文章講述使用 litePal 完成書架,敬請期待!!!