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