Button、ImageButton及ImageView詳解
在應用程序開發過程中,很多時候需要將View的background或者src屬性設置為圖片,即美觀又支持點擊等操作。常見的有Button、ImageButton及Imageview,以ImageView為例,在圖片瀏覽器或者編輯工具的開發中使用得非常廣泛。由於三者之間存在非常緊密的聯系,又有微妙的差別,有時候會傻傻地分不清到底該用誰。本篇文章通過概念講解與代碼分析的形式對它們做一個詳細的總結,完全清楚的小伙伴希望指出文中描述的不足之處。
1、基本概念
Button,普通按鈕,是各種UI中最常用的組件之一,也是Android開發中最受歡迎的組件之一,用戶可以通過觸摸它來觸發一系列事件。按鈕的樣式默認為系統按鈕的背景,不同的設備、不同的平台版本有不同的按鈕風格。其類結構圖如下:

ImageButton,顯示一個可以被用戶點擊的圖片按鈕,默認情況下,ImageButton看起來像一個普通的按鈕。按鈕的圖片可用通過<ImageButton> XML元素的android:src屬性或setImageResource(int)方法指定。要刪除按鈕的背景,可以定義自己的背景圖片或設置背景為透明。其類結構圖如下:

ImageView,顯示任意圖像(包括圖標),可以加載各種來源的圖片(如資源或圖片庫),實際應用中需要計算圖像的尺寸以達到最佳效果,並提供例如縮放和着色(渲染)等各種顯示選項。類結構圖如下:

組件支持的屬性與響應的方法在后面對異同點進行對比分析時會給出。
2、相似點
通過XML布局設計與Java代碼實現可以發現,Button、ImageButton及Imageview的相似之處有以下三點(只列出常用的,下同):
A、背景圖片,三者均可以通過android:background=”@drawable/imgName”來設置背景圖片;設置后效果圖如下:

B、背景顏色,三者均可以通過android:background=”#RGB”來設置背景顏色;為方便觀察,同時設置了ImageButton和ImageView組件的src屬性(資源圖片),設置后效果圖如下:

C、觸摸事件,三者均可以定義用戶觸摸時的響應方法,如最常用的點擊事件監聽器setOnClickListener()對應的onClick()方法;響應函數展示圖如下:

3、不同點
類似的,Button、ImageButton及Imageview的不同之處有以下三點:
A、資源圖片,Button不支持android:src=”@drawable/imgName”屬性,而ImageButton和ImageView可以通過該屬性來設置資源圖片(前景圖較易理解);設置后效果圖如下面左圖,而右圖是彈出的Button屬性選擇框,確實不存在src屬性;

B、文本內容,ImageButton和ImageView不支持android:text=”@string/textContent”屬性,而Button可以通過該屬性來定義按鈕名稱;設置后效果圖如下,兩者的屬性選擇框這里就不給出了;

C、響應方法,ImageView能夠實現的方法有限,而Button和ImageButton相對來來說多一些,如設置視圖的過滾動模式方法setOverScrollMode(int mode),從上述2中的響應方法展示圖中可以看出;
注意:雖然某個組件不支持某個屬性,但在XMl文件中定義時為其添加該屬性(自動彈出的屬性選擇框中沒有,可以手寫)並不會有任何警告或者錯誤,只是也不會有任何反應,即不會出現對應的效果。
4、XML代碼
Button、ImageButton及ImageView組件各定義了一個,分別添加了TextView組件用以說明當前組件類型,且均設置了background、src及text屬性。這里給出最終的xml文件代碼:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 android:gravity="center_vertical" > 7 8 <LinearLayout 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:orientation="horizontal" 12 android:layout_gravity="right" 13 android:layout_marginRight="50dp" 14 android:gravity="center_vertical" > 15 16 <TextView 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:paddingRight="20dp" 20 android:text="@string/btn" 21 android:textSize="20sp" 22 android:textColor="#f00" /> 23 24 <Button android:id="@+id/btn" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:gravity="center" 28 android:background="@drawable/btn" 29 android:src="@drawable/btn" 30 android:text="@string/btn" 31 android:textColor="#f00" /> 32 33 </LinearLayout> 34 35 <LinearLayout 36 android:layout_width="wrap_content" 37 android:layout_height="wrap_content" 38 android:orientation="horizontal" 39 android:layout_gravity="right" 40 android:layout_marginRight="50dp" 41 android:gravity="center_vertical" 42 android:layout_marginTop="50dp" > 43 44 <TextView 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:paddingRight="20dp" 48 android:text="@string/imgbtn" 49 android:textSize="20sp" 50 android:textColor="#0f0" /> 51 52 <ImageButton android:id="@+id/imgbtn" 53 android:contentDescription="@null" 54 android:layout_width="wrap_content" 55 android:layout_height="wrap_content" 56 android:gravity="center" 57 android:src="@drawable/imgbtn" 58 android:background="#0f0" 59 android:text="@string/imgbtn" 60 android:textColor="#f00" /> 61 62 </LinearLayout> 63 64 <LinearLayout 65 android:layout_width="wrap_content" 66 android:layout_height="wrap_content" 67 android:orientation="horizontal" 68 android:layout_gravity="right" 69 android:layout_marginRight="50dp" 70 android:gravity="center_vertical" 71 android:layout_marginTop="50dp" > 72 73 <TextView 74 android:layout_width="wrap_content" 75 android:layout_height="wrap_content" 76 android:paddingRight="20dp" 77 android:text="@string/imgview" 78 android:textSize="20sp" 79 android:textColor="#00f" /> 80 81 <ImageView android:id="@+id/imgview" 82 android:contentDescription="@null" 83 android:layout_width="wrap_content" 84 android:layout_height="wrap_content" 85 android:gravity="center" 86 android:src="@drawable/imgview" 87 android:background="#00f" 88 android:text="@string/imgview" 89 android:textColor="#f00" /> 90 91 </LinearLayout> 92 93 </LinearLayout>
最終的效果圖如下:

5、總結
本文主要從Android組件的src、background、text及onClick四個屬性,通過圖文的形式講解了Button、ImageButton及ImageView三者之間的異同點。至於在Java代碼中讓它們完成哪些具體的操作,需要根據實際的應用情況來進行實現,這里就不舉例了。
在布局設計與組件屬性設置過程中可以發現一個很有趣的現象(從上面的大部分效果圖中也可見,右下角的黃色感嘆三角):將TextView與ImageView這兩個組件加入同一個LinearLayout后,Eclipse會提示一個警告。截圖如下:

大致意思是說:如果要為TextView組件添加圖標,可以通過其自身的屬性來完成。什么也沒想,直接通過android:drawableLeft=”@drawable/imgName”在其左邊放一張圖片(此處用工程中默認圖標),然后將原本的ImageView組件去除,果然,警告消失了。如圖:

當然,實際開發時該用ImageView還是得用。個人覺得有趣是因為當前的Eclipse會根據添加的組件及位置來猜測開發者的意圖,並進行相應的判斷,必要時給出提示。像上述情況,它得出的結論可能是我想在TextView文本后面放一個對應的標志性圖標,而沒有判斷出其自身在這里只作為一個標志性文本。
說到警告,雖然一般不會影響到程序的正常運行,但總歸是一個缺陷。若用Lint工具對整個項目進行分析,就可以發現,資源與代碼冗余現象普遍存在,久而久之,會影響到項目的管理與維護。
如Eclipse和Lint均會提示ImageView和ImageButton這兩個組件在XMl文件中定義時需要設置contentDescription(描述)屬性,官方的解釋是為視力不便者提供使用說明文本,可見Google考慮得相當周到。不過大部分應用是不需要設置什么組件說明文本的,最簡單也是最高效的消除該警告的方法是在組件屬性中加入如下代碼:
1 android: contentDescription=”@null”;
