在之前的學習中我們接觸到了一些簡單常用的控件和監聽器,但這些在實際開發中是遠遠不夠的,接下來一起來認識更高級的控件和更豐富的監聽器,以及學會如何使用適配器搭建起數據源和視圖界面的橋梁。高級控件篇第的一部分將圍繞適配器講解它是如何在某些高級控件發揮重要作用。本篇控件清單:
- ListView 列表
- Spinner 下拉列表
- GridView 網格視圖
- ViewPager 視圖滑動切換工具
那什么是數據適配器Adapter呢?如開頭所說,它的作用是把復雜的數據填充在指定視圖界面上。常用兩種Adapter:ArrayAdapter(用于綁定單一的數據,數據源是數組或集合),SimpleAdapter(用于綁定格式復雜的數據,數據源是特定的泛型集合)。接下來將以ListView為例,看看這兩種適配器的使用方法和效果。
1.ListView 列表
ListView是最為常用的控件之一,它以列表的形式展示具體內容,并且能夠根據數據的長度自適應顯示。下圖是一個每項數據只有一行文本的ListView效果圖,對于這類單一數據,用ArrayAdapter加載數據再合適不過,接下來一起學習一下。
布局界面只需要一個ListView,設置好寬高和id就夠了。另外,還常用屬性android:divider設置列表分割線的顏色,如透明色#00000000.
在MainActivity用id找到布局中的ListView之后,就是加載適配器的過程了:
可以看到使用過程無非三個步驟:數據源準備->適配器加載數據源->控件加載適配器,在關鍵的第二步對ArrayAdapter初始化中,提供的三個參數完成了在哪里顯示、每一項數據如何顯示(這里直接使用安卓提供好一個布局)、顯示哪些數據及有多少項這些任務,再set到ListView上,就實現了一開始看到的界面效果。所以ListView只負責加載和管理視圖,其他顯示內容都是交給Adapter去做的。
當然ListView的每一項Item都是可以被監聽的,監聽器是OnItemClickListener,其中返回的參數position表示被點擊的某項在整個List中的位置,從0起算,這樣就能用ListView的getItemAtPosition()方法獲取到被點擊項的內容:
當點擊第一項“wifi”時效果如下:
接下來再看一個頁面效果:
在這個ListView能看到每個Item不再是簡單的一行,有文字也有圖片,這種格式復雜的數據就要用到SimpleAdapter了,還是在main.xml里準備好ListView控件,再回到MainActivity來學習如何用之前學會的三步驟來加載SimpleAdapter吧!
第一步準備數據源,可以看到數據源dataList是一個特定的泛型集合,這里String代表文字,Object代表圖片,然后調用getData()初始化dataList。
每一個Map對應一項Item,為了方便用for循環讓每個Item里圖標都一樣,文字內容遞增就可以,然后添加到dataList,這樣就完成一個有20項Item的List。這里注意Map鍵值對里的鍵名,后面會需要。
第二步適配器加載數據源,在此之前,需要給列表每一項做個布局item.xml,這個不難理解,因為在ArrayAdpter例子里我們直接使用系統提供的布局而已。注意要給出TextView和ImageView的id,馬上就會用到。
現在又到了關鍵一步,SimpleAdapter初始化比較復雜,需要用到五個參數,前三個容易理解,后兩個就是之前需要留心的兩個要點。這一步實現了控件與數據的一一綁定。最后一步加載適配器就大功告成了!
現在再介紹ListView上常用的監聽器OnScrollListener,用于監聽滾動變化,當用戶拉到列表最底下的時候可幫助視圖在滾動中加載數據。現在為列表設置監聽器listView.setOnScrollListener(this),并實現onScrollStateChanged ()、onScroll()方法。
這里重寫第一個方法,能看到事件會返回一個scrollState,它有三個狀態值,下圖打印出詳細描述。因為需要在視圖一直滑動到底端給出新的Item,為dataList增添新的map之后,要用到adpter非常關鍵的方法notifyDataSetChanged()通知適配器數據發生了變化要重新加載數據,這再次印證之前所說數據的顯示是適配器的工作而不是列表。
效果如下,可以看到當用戶看完20項繼續向下拖時就會有源源不斷的新內容更新上來。
學完這兩個常用適配器使用和適用情況之后,對比可看出ArrayAdapter使用起來明顯簡單許多,思考一個問題,ArrayAdapter的第二個參數如果不用系統提供的列表項布局而是自定義布局,是否也能做到圖文并存的效果呢?答案是肯定的,只不過需要自定義一個適配器繼承ArrayAdapter并重寫一些方法了。下面就來學習如何定制一個ListView界面吧!
這次做一個更好看的界面,準備好小動物的圖片就可以開始大展身手了!
回憶一下實例化一個ArrayAdapter時需要的三個參數,其中列表項布局以及適配器的適配類型都是要重新考慮的。那么先就從這開始準備吧!
每個Item都是由左邊一張圖片和右邊一行文本組成的,下面代碼中需要解釋的是使用tools:的屬性在我們預覽能看到效果但不會出現在運行后的布局,方便我們提前看效果又不至于影響后續工作。
接著需要準備一個實體類Animal作為適配器的適配類型,這個類里提供動物圖片和名稱兩個屬性、用來初始化屬性的構造方法以及對應的get方法即可。
然后到了關鍵一步,創建一個自定義的適配器且繼承ArrayAdapter,重寫父類一組含三個參數的構造函數,并將列表項子布局的id保存下來。接著重寫getView()方法,先用getItem(position)得到當前Item項的Animal實例,再用LayoutInflater系列方法把子布局傳入當前布局得到一個View,接著調用這個View的findViewById()找到ImageView和TextView實例,這樣就可以把從當前項對象get的內容設置到這兩個控件里去顯示圖片和文字了。
一切準備就緒之后,后面的步驟基本信手拈來了,相信下面這段代碼你一定沒問題了。
點擊某個Item也會有響應:
這里對getView()多提幾句,如果我們只是用上面幾行代碼來運行ListView的話效率會非常低,因為每次為了要顯示每個子項去調用getView()方法后都會將布局重新加載一遍,如果能將顯示過的Item View緩存起來,以后出現直接復用就能達到提升ListView運行效率的效果了。優化后代碼如下:
以下是源代碼:
public View getView(int position, View convertView, ViewGroup parent) {
Animal animal=getItem(position);
View view;
ViewHolder viewHolder;
if(convertView==null){
view=LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder=new ViewHolder();
viewHolder.imageView= (ImageView) view.findViewById(R.id.animal_image);
viewHolder.textView= (TextView) view.findViewById(R.id.animal_name);
view.setTag(viewHolder);
}else{
view=convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.textView.setText(animal.getAnimalName());
viewHolder.imageView.setImageResource(animal.getImageId());
return view;
}
class ViewHolder{
ImageView imageView;
TextView textView;
}
}
到此學了這么多,相信你對適配器可以熟練使用了吧!只要三步就搞定。想必在其他控件上應用適配器也很容易了,下面快來再認識兩個高級控件。
2.Spinner 下拉列表
與ListView類似的,每個下拉列表項對應一個Item,列表項內容一般是文字,用ArrayAdapter就能做到,觸類旁通,相信做一個下圖所示的下拉列表已經難不倒你了!
選擇系統提供的一個布局作為Spinnner的菜單樣式,注意是設置在適配器上,這里給Spinner安裝監聽器是OnItemSelectListener,用適配器和列表都可以定位到某Item,完成后效果如下:
3.GridView 網格視圖
從名字中能看出來GridView的特點,它使得每個Item以網格的形式展現,除此之外使用方式和ListView非常相似。下面準備用SimpleAdapter做一個這樣的Demo:
GirdView本身還有些常用的屬性: android:verticalSpacing(兩列之間的間距),android:horizontalSpacing(兩行之間的間距), android:numColumns(每行顯示多少列,選值為auto_fit表示自動適應展示幾列)。
接下來就是GridView綁定SimpleAdapter的過程了,不再細說,需要強調這里把圖標和文字分別放在兩個數組中且一一對應以便能通過循環得到數據源dataList。監聽器是OnItemClickListener。
最后為了界面美觀,在注冊該活動時候設置theme是Black且NoTitleBar,注意被設置成android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"的活動一定繼承的是android.app包下Activity,如果是V7兼容包下的AppCompatActivity會導致程序崩潰無法打開。點擊運行來看看是不是達到上面的效果了呢?
其實除了這兩個常用Adatper,還有一些Adapter也實用,下面通過ViewPager控件再來認識一個Adapter。
4.ViewPager 視圖滑動切換工具
ViewPager是android擴展包v4包中的類,這個類可以讓用戶左右切換當前的視圖(View、Fragment都可以),很多APP都用到這個功能,可見其重要程度,因此想用這點篇幅詳解ViewPager是完全不夠的,這里就僅僅給大家介紹用來幫助ViewPager管理View數據源的適配器PagerAdapter,感受一下風格各樣的適配器。
首先在布局里導入v4包兩個控件,其中PagerTabStrip是ViewPager子標簽,包含在ViewPager里,這里用它作標題。
由于PagerAdapter是抽象類,使用時需要自定義子類。初始化時讓這個適配器獲取到兩個數據源List:頁卡List和標題List,之后重寫幾個方法更好的完善這個適配器的功能。
接著三步驟,在主活動準備好兩個List,這里用View.inflate ()方法將布局轉化成View對象,數據加載到自定義適配器上,adapter加載到ViewPager即可,又給ViewPager設置監聽器OnPageChangeListener監聽頁卡是否發生變化。另外,我們還獲取到控件PagerTabStrip去給標題做些美化工作。
最后效果如圖,手指左右滑動就可以實現頁面切換了。
其實所有這些Adapter都是從父類BaseAdapter擴展而來的,也就是說我們也可以根據自己的需要自定義一個Adapter繼承BaseAdapter,然后具體實現下面4個方法:
由于adapter中含有要顯示的數據集合,數據集合中元素個數即可被展示的View個數,每個數據的獲取、每個Item View的樣式都由adapter控制,每個position位置上數據都綁定到Item View上,這樣數據和視圖也就結合在一起了。由于篇幅原因不在這里接著具體展開,后續再深入探究。
本篇先到這里,下一篇還有更多有趣的高級控件等我們學習~