Android常用控件用法
包含Checkbox 二、RadioButton 三、ImageView 四、深入LinearLayout 五、相對布局 六、TimePicker 七、DatePicker。
一、Checkbox
1.布局文件的定義
<CheckBox
android:id="@+id/eatId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吃飯"/>
<CheckBox
android:id="@+id/sleepId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="睡覺"/>
<CheckBox
android:id="@+id/dotaId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dota"/>
2.Activity中的使用
先聲明三個成員變量:
private CheckBox eatBox;
private CheckBox sleepBox;
private CheckBox dotaBox;
再在onCreate函數里找到它們
eatBox = (CheckBox) findViewById(R.id.eatId);
sleepBox = (CheckBox) findViewById(R.id.sleepId);
dotaBox = (CheckBox) findViewById(R.id.dotaId);
3.OnClickListener監聽器
現在需要定義一個監聽器,監聽click這個事件
class onClickBoxListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODOAuto-generated method stub
System.out.println("Checkbox is clicked!");
}
}
然后在onCreate函數實例化這個監聽器
onClickBoxListener listener = new onClickBoxListener();
將監聽器綁定到Checkbox上。這里可以把一個listener綁定到多個控件。
eatBox.setOnClickListener(listener);
sleepBox.setOnClickListener(listener);
dotaBox.setOnClickListener(listener);
現在運行這個程序,如圖:
三個選項出現,我們進行勾選,Eclipse的后臺會顯示Checkbox is clicked!
1) 在監聽器中獲取checkbox 的ID
雖然實現了基本流程,但是有一個問題沒有解決,不管我勾選或取消哪個Checkbox,響應的行為都是一樣的,而且不知道是選中還是取消選中。這滿足不了編程的需要。
要實現這種功能,我們要通過監聽器傳參:
public void onClick(View v) {
// TODOAuto-generated method stub
System.out.println("Checkbox is clicked!");
}
函數里的v是View類型,它有一個方法是getId(),它得到的就是控件的ID。
現在事情就很好辦了。
if (v.getId() == R.id.eatId){
System.out.println("eatBox");
} else if (v.getId() == R.id.sleepId){
System.out.println("sleepBox");
} else if (v.getId() == R.id.dotaId){
System.out.println("dotaBox");
}
2) 在監聽器中獲取checkbox 的選中狀態
我們需要知道,對某個checkbox操作的是選中還是取消選中。
還是通過v這個參數,由于這個參數是View類型,我們需要向下轉型為CheckBox,才能獲取選中狀態。
CheckBox checkbox = (CheckBox) v;
CheckBox類型有一個方法,是isChecked()。返回值是真,表示選中,返回值是假,表示未選中。
4.OnCheckedChangeListener監聽器
依然是定義一個監聽器,監聽CheckedChange這個事件,即Checkbox的選中狀態發生改變時:
class boxListener implements OnCheckedChangeListener{
}
導入包的時候注意,選CompoundButton這個。Checkbox其實是它的子類。
添加未實現的方法時,我們發現函數的傳參是個CompoundButton類型,還有第二個參數,是個布爾值。
當選中狀態發生改變時,就把控件對象和當前狀態傳遞進來。
@Override
public void onCheckedChanged(CompoundButton buttonView,
booleanisChecked) {
// TODO Auto-generated method stub
}
照舊是實例化這個監聽器,綁定到控件上。
boxListener listener2 = new boxListener();
eatBox.setOnCheckedChangeListener(listener2);
sleepBox.setOnCheckedChangeListener(listener2);
dotaBox.setOnCheckedChangeListener(listener2);
現在我們來完善監聽代碼
if (buttonView.getId() == R.id.eatId){
System.out.println("eatBox Changed");
if (isChecked)
System.out.println("eatBox Changed True");
}
不用多說了,這對程序員來說已經很簡單了。
OnClickListener監聽和OnCheckedChangeListener監聽的區別在于:
前者是監聽點擊事件,后者是監聽狀態的改變,因為狀態的改變不全是由于直接的點擊,也可以是由于代碼的控制,代碼里設置checkbox狀態的函數是setChecked(狀態) ,狀態的值是true或false。
二、RadioButton
1.布局文件的定義
RadioGroup是指一組單選按鍵,一組單選按鈕只能選中一個。RadioButton是RadioGroup的子標簽(RadioButton與RadioGroup分別是不同的控件)。所以在布局文件里,要先定義一個RadioGroup,內部再包含RadioButton。
<RadioGroup
android:id="@+id/radios"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/femaleId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="female"
/>
<RadioButton
android:id="@+id/maleId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="male"
/>
</RadioGroup>
注意:RadioGroup有個特殊的屬性orientation,是指各單選按鈕的排列方向,可以設置水平或垂直。
2.Activity中的使用
聲明成員變量,注意RadioGroup與RadioButton分開聲明:
private RadioGroupradioGroup;
privateRadioButton femaleButton;
privateRadioButton maleButton;
findViewById找到它們:
radioGroup = (RadioGroup) findViewById(R.id.radios);
femaleButton = (RadioButton) findViewById(R.id.femaleId);
maleButton = (RadioButton) findViewById(R.id.maleId);
實現選中之后的行為,需要綁定監聽器了。
3.OnClickListener監聽器
可以給RadioButton添加OnClickListener,監聽各個RadioButton被點擊的狀態。操作方法與前一講Checkbox類似,此不贅述。
4.OnCheckedChangeListener監聽器
1) RadioGroup的OnCheckedChangeListener
給RadioGroup綁定監聽器OnCheckedChangeListener,表示當這個RadioGroup內部的RadioButton被選中時,就會調用OnCheckedChangeListener監聽器:
class listener implements OnCheckedChangeListener(){
}
在導入包的時候注意了,這與Checkbox不同,我們須選擇第二個
導入包以后,onCreate里綁定到RadioGroup:
listener listener = new listener();
radioGroup.setOnCheckedChangeListener(listener);
然后在監聽器里實現未實現的函數:
class listener implements OnCheckedChangeListener{
@Override
public voidonCheckedChanged(RadioGroup group, int checkedId) {
}
}
發現這個函數有兩個參數,
第二個參數代表這個RadioGroup里被選中的RadioButton的ID,因為同時被選中的只可能有一個嘛,所以就直接傳進來了。
實現監聽器的代碼:
public voidonCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.femaleId){
System.out.println("femaleId is checked");
} else {
System.out.println("maleId is checked");
}
}
2) RadioButton的OnCheckedChangeListener
定義這個監聽器的時候,要特別注意,實現的接口不是RadioGroup.OnCheckedChangeListener,而是CompoundButton.OnCheckedChangeListener。
于是我們定義這個監聽器的時候,為避免重名,要寫全:
class listener2 implements android.widget.CompoundButton.OnCheckedChangeListener{
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
}
}
為什么是CompoundButton?
這里解釋一下,所謂CompoundButton,是指兩種狀態的button的抽象父類,Checkbox和RadioButton都是它的子類。
綁定它到femaleButton上:
listener2 listener2 = new listener2();
femaleButton.setOnCheckedChangeListener(listener2);
如此表示,當femaleButton的選中狀態發生改變時,觸發listener2監聽器里的代碼。
注意:如果我們選中了maleButton,也會調用這個監聽器,因為選中maleButton的同時,femaleButton的選中狀態也發生了改變。
我們實現這個監聽器里的代碼:
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
System.out.println("female is "+ isChecked);
}
第二個參數就是當前選中的狀態。
三、ImageView
1.布局文件的定義
<ImageView
android:id="@+id/imageId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq" />
這里有個src屬性,很好理解,不過里面的東東是怎么來的呢?
之前我們提到過的res這個資源目錄,里面的drawable表示存放圖片。
我們將圖片拷進目錄:
R.java文件會自動生成它的ID:
public static final class drawable {
public static final int ic_launcher=0x7f020000;
public static final int qq=0x7f020001;
}
因此,我們使用android:src="@drawable/qq"就可以引用到它了。
2.Activity中的使用
聲明變量
private ImageView image;
找到控件
image = (ImageView) findViewById(R.id.imageId);
之前是在布局文件中設置它的源文件,也可以在代碼中設置:
image.setImageResource(R.drawable.qq);
3.ScaleType屬性
現在的問題是,圖片鋪不滿全屏。ScaleType就是用來解決這個問題的,它用于定義圖片拉伸的類型是什么。
先讓我們把準備工作做好,寫兩個ImageView寫好高寬和背景色,以方便做對比。
上一張是剛才那只賣萌狗,下一張是安卓機器人圖標:
<ImageView
android:id="@+id/imageId"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF0000"
android:scaleType="center"
android:src="@drawable/qq" />
<ImageView
android:id="@+id/image2Id"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00FF00"
android:scaleType="center"
android:src="@drawable/ic_launcher"/>
ScaleType有以下幾種,讓我們來分別試驗一下:
1) center
不縮放。
如果圖比ImageView小,就居中。如果圖比ImageView大,就截取中間部分。
2) centerCrop
等比例縮放。
并以短邊為準鋪滿。長出的部分截掉。
3) centerInside
等比例縮小并居中對齊。
如果圖比ImageView小,就不變。如果圖比ImageView大,就縮小。
4) fitCenter
等比例縮放并居中對齊。
如果圖比ImageView小,就放大。如果圖比ImageView大,就縮小。
5) fitStart
等比例縮放并靠左上角對齊。
6) fitEnd
等比例縮放并靠右下角對齊。
7) fitXY
不等比例縮放,拉伸為與ImageView同樣大小。
在代碼里怎么控制scaleType呢?
image.setScaleType(ScaleType.CENTER);
四、深入LinearLayout
1.LinearLayout的嵌套
這樣一個布局用一個LinearLayout是無法實現的。需要用到LinearLayout的嵌套。
布局代碼如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:orientation="horizontal"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#880000"
android:layout_marginRight="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="first"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="second"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#880000"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="first"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="second"/>
</LinearLayout>
</LinearLayout>
這個嵌套對程序員來說太容易理解了,就不多說了。
2.layout_weight屬性
Layout_weight這個屬性的值用于指定空閑空間的分配比例,如下圖:
使用layout_weight,要求子控件并未占滿你控件的所有空間。否則這個屬性將不具意義。
Layout_weight的值是整型。
例如,上面這張圖,如果我們給兩個控件的layout_weight分別給定值1:
那么,這兩個控件將平分空閑空間。達到的效果見下圖:
有一點需要特別注意:
layout_weight=1不代表兩個控件平分父控件的空間,而是在本身占據的空間基礎上,將剩下的空間一分為二,分別加給兩控件。所以,兩控件并不一定是各占父控件的二分之一的。
見下圖:
紅線所劃的距離是相等的。而綠色和藍色的長度卻不等。
這是layout_weight為1的情況,如果將控件一的layout_weight設為2呢?
那么,就將剩余空間平均分為三份,其中兩份給控件一,一份給控件二。
以此類推。
我們在實際開發中常常需要讓控件占父控件的1/2,或1/3等等。這樣layout_weight就滿足不了我們的要求。但有個辦法可以做到:
將控件的寬不再wrap_content,而是設為0dp。
五、相對布局
1.什么是相對布局
相對布局是通過指定當前控件與兄弟控件或父控件之間的相對位置,從而達到控制控件位置的目的。
和線性布局相比有什么優勢呢?看下面這張圖:
這個布局如果用線性布局,需要嵌套好幾層,而如果用相對布局,一個布局就搞定了。
對Android UI來說,幾層布局嵌套,性能比一個布局要差。
2.相對布局基本思路
先確定一個控件的位置,第二個控件,確定它相對于第一個控件的位置。
這種情況下,如果第一個控件因為某種原因發生位置改變,那么,第二個控件與它的相對位置不變,也跟著位移。
在相對布局中,如果不指定相對位置,默認會放在父控件的左上角:
如果第二個控件也不指定相對位置,那么,第二個控件會覆蓋第一個控件,仍然放在左上角:
要實現相對布局,就要指定相對位置,以下我們分別介紹:
1) 與兄弟控件邊緣對齊
layout_toRightOf
把當前控件的左邊緣對齊到指定控件的右邊緣。
第一個控件給定ID為first:
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="第一個控件" />
第二個控件設置layout_toRightOf屬性為@id/first:
注意:這里沒有+,+表示增加一個id
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_toRightOf="@id/first"
android:text="第二個控件" />
這樣就能把第二個控件放置在第一個控件的右邊
layout_toLeftOf
把當前控件的右邊緣對齊到指定控件的左邊緣。
理同layout_toRightOf
如果第一個控件沒有指定相對位置,而第二個控件指定到它的左邊緣,那么第二個控件會被擠到屏幕外面,不可見。見下圖:
layout_below
把當前控件的上邊緣對齊到指定控件的下邊緣。
layout_above
把當前控件的上邊緣對齊到指定控件的下邊緣。
同layout_toLeftOf理,在屏幕外,不可見了。
layout_alignLeft
把當前控件的左邊緣對齊到指定控件的左邊緣。
我們先把第一個控件的文本改得“第一個控件比較長”,這樣看得出來。
把第二個控件的layout_alignLeft值設為@id/first:
第一個控件被覆蓋掉了一部分。
layout_alignRight
把當前控件的右邊緣對齊到指定控件的右邊緣。
理同layout_alignLeft
layout_alignTop
把當前控件的上邊緣對齊到指定控件的上邊緣。
layout_alignBottom
把當前控件的下邊緣對齊到指定控件的下邊緣。
2) 與兄弟控件基準線對齊
什么是基準線
基準線(baseline):為了保證印刷字母的整齊而劃定的線。這主要針對英文,對于中文其實沒有這個問題。
第三條線就是基準線。
對齊到基準線的屬性是layout_alignBaseLine。
layout_alignBaseLine
把當前控件的基準線對齊到指定控件的基準線。
沿用之前的代碼,第二個控件的定義如下:
<TextView
android:id="@+id/second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_alignBaseline="@id/first"
android:layout_toRightOf="@id/first"
android:text="第二個控件" />
定義了兩個對齊屬性,layout_alignBaseline和layout_toRightOf都指定為@id/first
為了比較明顯,把第一個控件的字體設大,為30sp。
效果如下:
對齊的不再是邊緣,而是字體的基準線。
3) 與父控件邊緣對齊
我們去掉第二個控件,將第一個控件設置以下屬性:
注意:這些屬性的值不再是某控件的id,而是true或false
layout_alignParentRight
把當前控件的右邊緣對齊到父控件的右邊緣。
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:textSize="30sp"
android:layout_alignParentRight="true"
android:text="第一個控件" />
layout_alignParentLeft
把當前控件的左邊緣對齊到父控件的左邊緣。
如果我同時設定layout_alignParentRight和layout_alignParentLeft都為true,會出現什么情況呢?
它的效果會疊加,即左邊緣對齊父控件的左邊緣,右邊緣對齊父控件的右邊緣。
layout_alignParentTop
把當前控件的上邊緣對齊到父控件的上邊緣。
理同layout_alignParentRight,可與其他三個屬性疊加。
比如可設置左上對齊,或右上對齊。
layout_alignParentBottom
把當前控件的右邊緣對齊到父控件的右邊緣。
理同layout_alignParentRight,可與其他三個屬性疊加。
比如可設置左下對齊,或右下對齊。
4) 與父控件中央對齊
layout_centerInParent
把當前控件對齊到父控件垂直和水平的中間位置。
layout_centerHorizontal
把當前控件對齊到父控件水平的中間位置。
layout_centerVertical
把當前控件對齊到父控件垂直的中間位置。
3.相對布局的新屬性(Android4.2)
為了使用這些新屬性,項目新建時,必須把最低的兼容屬性也調整到4.2,否則使用不了這些屬性。
layout_alignStart
把當前控件對齊到指定控件的起始位置。
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_alignEnd="@id/first"
android:text="abc" />
可以和layout_below一起用:
layout_alignEnd
把當前控件對齊到指定控件的結束位置。
和layout_below一起用時的效果:
layout_alignParentStart
把當前控件的頭部對齊到父控件的開始位置。
值為true或false。
layout_alignParentEnd
把當前控件的尾部對齊到父控件的尾部。
值為true或false。
4.綜合運用
來個實用的例子:
實現這個界面之前,先記住兩個之前沒有提過的東西:
1.內容居中
android:gravity="center"
2.文本框
EditText。
EditText有個屬性叫hint,表示文本框在未輸入前的提示信息:
android:hint="請輸入內容"
還有個屬性叫inputType,表示輸入的類型,如文本(text)、日期(date)、日期時間(datetime)、數字(number)、電話(phone)、密碼(textPassword)等等。
android:inputType="textPassword"
動手做一做吧。
六、TimePicker
1.布局文件的定義
<TimePicker
android:id="@+id/timeId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
效果如下圖:
2.Acitivity中的使用
聲明這個變量
private TimePicker timePicker;
找到這個控件
timePicker = (TimePicker) findViewById(R.id.timeId);
3.OnTimeChangedListener監聽器
定義這個監聽器:
class Listener implementsOnTimeChangedListener{
@Override
public voidonTimeChanged(TimePicker view, int hourOfDay, int minute) {
System.out.println("hour:"+hourOfDay+",minute:"+minute);
}
}
綁定到之前的控件:
Listener Listener=new Listener();
timePicker.setOnTimeChangedListener(Listener);
觀察未實現的方法,有三個參數:
第二個參數hourOfDay表示用戶選擇的小時
第三個參數minute表示用戶選擇的分鐘
4.24小時制
用一行代碼可以做到:
timePicker.setIs24HourView(true);
5.選定以后提交
如果不要一直變化,而要用戶選定以后再點確定提交,怎么做呢?
先加個Button:
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="確定"
android:layout_below="@id/timeId"
/>
在Activity里聲明它
private Button submit;
找出它
submit = (Button) findViewById(R.id.submit);
定義一個OnClickListener的監聽器
class listener2 implementsOnClickListener{
@Override
public void onClick(View v) {
int Hour = timePicker.getCurrentHour();
int Minute = timePicker.getCurrentMinute();
System.out.println("hour:"+Hour+",minute:"+Minute);
}
}
int Hour = timePicker.getCurrentHour();表示獲取當前選擇的小時數。
int Minute = timePicker.getCurrentMinute();表示獲取當前選擇的分鐘數。
綁定這個監聽器到Button上。
listener2 listener2=new listener2();
submit.setOnClickListener(listener2);
6.設定初始時間
TimePicker默認顯示當前時間。可以設置:
timePicker.setCurrentHour(10);
timePicker.setCurrentMinute(00);
七、DatePicker
1.布局文件的定義
定義一個DatePicker和一個Button
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/datePicker"
android:text="提交"
/>