GiáotrìnhAndroid
GiaodiệnngườidùngcủaứngdụngAndroid
TrongcácchươngtrướctađãlàmquenvớithànhphầncơbảncủagiaodiệnAndroidlàActivityvàvòngđờicủanó.Tuy
nhiên,bảnthânActivitykhôngphảilàthứchúngtanhìnthấytrênmànhìnhđiệnthoại,thayvàođóActivitycầncócác
thànhphầnđồhọakhácbêntrongnó,làcácViewvàViewGroup.Trongchươngnàychúngtasẽtìmhiểuchitiếthơnvề
cácViewvàViewGrouptrongAndroidđểtạonêngiaodiệnđồhọacủaứngdụng,cũngnhưcáchthứctươngtácvới
chúng.
GiaodiệnngườidùngcủaứngdụngAndroid
65
GiáotrìnhAndroid
ViewvàViewGroup
Nhưđãđềcậpởtrên,mỗiActivitymuốnhiểnthịgiaodiệnđồhọacầnchứacácthànhphầngiaodiệnkhácnhưnútbấm,
cácnhãn,cácônhậpliệu,checkbox,radiobutton…NhữngthànhphầnnhưvậytrongAndroidđượcgọichunglàcác
View.TấtcảcácViewđềuđượckếthừatừlớpandroid.view.View.
MộthoặcnhiềuViewcóthểđượcnhómlạivớinhauthànhmộtViewGroup.MỗiViewGroupcũnglàmộtView,đượcdùng
đểnhómcácViewconbêntrongnóvàhiểnthịchúngtheomộtthứtựhayquyluậtnàođó.MọiViewGroupđềuđượckế
thừatừlớpandroid.view.ViewGroup.CácloạiViewGroupphổbiếnnhấttrongAndroidbaogồm:
LinearLayout
AbsoluteLayout
TableLayout
RelativeLayout
FrameLayout
ScrollView
CácViewvàViewGrouptạothànhgiaodiệncủaActivityvàthườngđượcmôtảngaytrongfilelayoutcủaActivity,nằm
trongthưmụcres/layout(filemain.xmltrongcácvídụtrước).Vídụ:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android=" />android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
android:layout_width="160dp"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="left"
android:layout_weight="1"/>
android:layout_width="160dp"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="center"
android:layout_weight="2"/>
android:layout_width="160dp"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="right"
android:layout_weight="3"/>
</LinearLayout>
MộtsốthuộctínhchungcủacácViewvàViewGroupđượckểratrongbảngdướiđây:
Thuộctính
Môtả
layout_width
ChiềurộngcủaView/ViewGroup
layout_height
ChiềucaocủaView/ViewGroup
layout_marginTop
Chiềurộngkhoảngtrống(lề)phíatrêncủaView
layout_marginBottom
Chiềurộngkhoảngtrống(lề)phíadướicủaView
layout_marginLeft
Chiềurộngkhoảngtrống(lề)phíabêntráicủaView
ViewvàViewGroup
66
GiáotrìnhAndroid
layout_marginRight
Chiềurộngkhoảngtrống(lề)phíabênphảicủaView
layout_gravity
CáchxếpđặtView(trái,phải,trên,dưới,giữatheochiềudọc,giữatheochiềungang)
PhầntiếptheosẽmôtảchitiếthơnvềmộtsốloạiViewGroupphổbiếntrên.Cầnchúýrằngtrongthựctếsửdụng,giao
diệnđồhọacủaứngdụngthườngđượctạothànhbởimộttổhợpphâncấpgiữacácloạiViewGroupkhácnhau.
LinearLayout
LinearLayoutsắpxếpcácviewconbêntrongnótheomộtcột(từtrênxuốngdưới)hoặctheomộthàng(từtráiquaphải).
Cácviewconđượcxếpdọchoặcngangtùythuộcvàothamsốandroid:orientationcủaLinearLayout,giátrịcủathamsố
nàycóthểlà“vertical”(dọc)hoặc“horizontal”(ngang).
Xemvídụsau:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android=" />android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/hello"/>
android:layout_width="160dp"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Button"/>
</LinearLayout>
GiaodiệntrênbaogồmmộtLinearLayouttheochiềudọc,chứa1viewbêntronglàđoạnchữ“Helloworld”vànútbấm
“Button”bêndướinó.ChiềurộngvàcaocủaLinearLayoutlàfill_parent,tứclànósẽchiếmhếtchiềurộng,chiềudàicủa
viewmẹ(trongtrườnghợpnàylàActivity,tứclàtoànmànhình).Chiềurộngcủatextviewlà100dp(điểmảnhkhôngphụ
thuộcvàomậtđộmànhình,chitiếtxembêndưới),chiềucaocủatextnàylàwrap_contenttứclàbằngđúngchiềucaocủa
nộidungchứatrongnó(phụthuộcvàosốdòngchữ,kíchthướcchữ,khoảngcách…thựctế).
CácđơnvịđokíchthướctrongAndroidbaogồm:
dp(hoặcdip)-Density-independentpixel(điểmảnhkhôngphụthuộcvàomậtđộmànhình).Mộtdptươngđươngvới
mộtpixeltrênmànhìnhcómậtđộ160dpi(160điểmảnhtrênmỗiinchmànhình).Đâylàđơnvịđượckhuyếnnghị
dùngtronghầuhếtcáctrườnghợpđặtkíchthướccủaviewtronglayout.Chitiếthơnvềmậtđộmànhìnhđượcđề
cậpởphầnsaucủagiáotrình.
sp-Scale-independentpixel,đơnvịnàytươngtựdp,đượcdùngkhimôtảkíchthướcfontchữ(fontsize)
pt-Point.1point=1/72inch,dựatrênkíchthướcvậtlýthậtcủamànhình.
px–Pixel–mộtpixelvậtlýtrênmànhình,đơnvịnàykhôngđượckhuyêndùngtrongthiếtkếgiaodiệnứngdụngvì
giaodiệnsẽhiểnthịkhôngđồngnhấttrêncácmànhìnhcóđộphângiảikhácnhau.
Trongvídụởtrên,nútbấmcóchiềurộnglà160dpvàtextviewlà100dp.Đểhiểuđượckíchthướcnày,trướchếttaxem
kháiniệmkíchthướcvàmậtđộmànhìnhtrongAndroid.Taxéttrênvídụcụthể:điệnthoạiNexusScủaGoogle.Thiếtbị
nàycómànhình4inchtheođườngchéo,2.04inchtheochiềungang,vớiđộphângiải480x800pixel.Chiềurộng2.04
inchvới480pixelchotamậtđộđiểmảnhkhoảng235dpi(dotsperinch–điểmảnhmỗiinch)–xemhìnhbêndưới.
ViewvàViewGroup
67
GiáotrìnhAndroid
Androidđịnhnghĩa4loạimậtđộmànhìnhnhưsau:
Mậtđộthấp:Lowdensity(ldpi)-120dpi
Mậtđộtrungbình:Mediumdensity(mdpi)-160dpi
Mậtđộcao:Highdensity(hdpi)-240dpi
Mậtđộrấtcao:ExtraHighdensity(xhdpi)-320dpi
Mỗithiếtbịsẽđượcxếpvàomộttrongcácloạimậtđộtrên.VídụthiếtbịNexusSởtrênsẽđượcxếpvàothiếtbịmậtđộ
cao,domậtđộmànhình(235dpi)gầnnhấtvớimậtđộhdpi–240dpi.CònđiệnthoạiTheHTCHero,cómànhình3.2inch,
độphângiải320x480,cómậtđộ180dpisẽđượcxếpvàođiệnthoạimậtđộtrungbình(mdpi)dogầnnhấtvớiconsố
160dpi.
Dướiđâylàhìnhảnhcủalayouttrênchạytrên2thiếtbịcókíchthướcvàđộphângiảikhácnhau.Hìnhbêntráilàthiếtbị4
inch,độphângiải480x800(mậtđộ235dpi–hdpi),hìnhbênphảilàthiếtbị3.2inch,độphângiải320x480(mậtđộ180dpi).
ViewvàViewGroup
68
GiáotrìnhAndroid
Cóthểthấymặcdùchạytrên2thiếtbịcóđộphângiải,kíchthướcvàmậtđộkhácnhau,nhưngnútbấmvàtextcókích
thướcrấtđồngnhất(nútbấmchiếmkhoảng1/2chiềungangmànhình).Kíchthướcthựctế(tínhbằngpixelvậtlý)được
tínhtừkíchthướcdpnhưsau:Kíchthướcpixelthựctế=dp*(dpi/160),trongđódpi=120,160,240,hoặc320tùythuộc
vàomànhìnhthiếtbị.
Ởvídụtrên,nútbấmtrênmànhìnhbêntráisẽcókíchthướcthậtlà:160*(240/160)=240pixel,còntrênmànhìnhbên
phảisẽlà160x(160/160)=160pixel.
Nếutathayđơnvịdptrongkhaibáolayoutởtrênthànhđơnvịpxnhưdướiđây:
android:layout_width="100px"
android:layout_height="wrap_content"
android:text="@string/hello"/>
android:layout_width="160px"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Button"/>
thìkếtquảsẽlà:
ViewvàViewGroup
69
GiáotrìnhAndroid
Nhưvậycóthểthấyviệcsửdụngđơnvịpxtrongthiếtkếgiaodiệnlàkhôngnên,mànênsửdụngđơnvịdp,đơnvịnàyđã
baogồmviệcthíchnghigiaodiệnvớicáckíchthướcmànhìnhkhácnhau.Nếuthaythamsố
android:orientation="vertical"củalinearlayoutthànhandroid:orientation="horizontal",sẽthuđược:
ViewvàViewGroup
70
GiáotrìnhAndroid
AbsoluteLayout
AbsoluteLayoutchophépđặtcácviewconbêntrongnótạivịtríchínhxác,cốđịnh,tínhtheopxhoặcdp.Layoutloạinày
khônglinhhoạtvàkhôngthíchnghiđượcvớisựthayđổicủađộphângiảimànhình,vìvậykhôngđượckhuyêndùng
trongcácphiênbảnAndroidgầnđây.Vìvậychođếnthờiđiểmhiệntại,tacóthểquênđiloạilayoutnày.
TableLayout
Tablelayoutchophépsắpxếpcácviewconbêntrongnótheodòngvàcột.Mỗidòngđượcđặttrongthẻ<TableRow>,mỗi
viewcontrongTableRowđượcđặttrongmộtôcủadòng,chiềurộngcủamỗicộtđượcxácđịnhbằngchiềurộnglớnnhất
củacácôtrongcộtđó.Xétvídụsau:
xmlns:android=" />android:layout_height="fill_parent"
android:layout_width="fill_parent"
>
<TableRow>
android:text="UserName:"
android:width="120dp"
/>
android:id="@+id/txtUserName"
android:width="200dp"/>
</TableRow>
<TableRow>
android:text="Password:"
/>
android:id="@+id/txtPassword"
android:password="true"
/>
</TableRow>
<TableRow>
<TextView/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="RememberPassword"
/>
</TableRow>
<TableRow>
android:id="@+id/buttonSignIn"
android:text="LogIn"/>
</TableRow>
</TableLayout>
Kếtquảcủalayouttrênkhichạytrênemulatorvớimànhìnhdọcvàngangsẽnhưsau:
ViewvàViewGroup
71
GiáotrìnhAndroid
RelativeLayout
RelativeLayoutchophépcácviewconbêntrongđượcsắpđặttươngđốivớinhauvàtươngđốisovớiviewmẹ.
android:id="@+id/RLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android=">
android:id="@+id/lblComments"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Comments"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
android:id="@+id/txtComments"
android:layout_width="fill_parent"
android:layout_height="170px"
android:textSize="18sp"
android:layout_alignLeft="@+id/lblComments"
android:layout_below="@+id/lblComments"
android:layout_centerHorizontal="true"/>
android:id="@+id/btnSave"
android:layout_width="125px"
android:layout_height="wrap_content"
android:text="Save"
android:layout_below="@+id/txtComments"
android:layout_alignRight="@+id/txtComments"/>
android:id="@+id/btnCancel"
android:layout_width="124px"
android:layout_height="wrap_content"
android:text="Cancel"
android:layout_below="@+id/txtComments"
android:layout_alignLeft="@+id/txtComments"/>
</RelativeLayout>
ViewvàViewGroup
72
GiáotrìnhAndroid
Kếtquảcủalayouttrênnhưsau:
Mỗiviewcontrongrelativelayoutcómộtsốthuộctínhnhấtđịnhgiúpchúngcănchỉnhtheoviewmẹhoặctheocácview
kháccùngcấp.Tacóthểthấycácthuộctínhnàytrongvídụởtrênnhư:
layout_alignParentTop–xếptrêncùngsovớilayoutmẹ
layout_alignParentLeft–căntráisovớilayoutmẹ
layout_alignLeft–căntráisovớilayoutkhác(cóidđượcchỉratronggiátrịcủathuộctínhnày)
layout_alignRight–căntráisovớilayoutkhác(cóidđượcchỉratronggiátrịcủathuộctínhnày)
layout_below–đặtxuốngdướilayoutkhác(cóidđượcchỉratronggiátrịcủathuộctínhnày)
layout_centerHorizontal–căngiữatheochiềungangsovớilayoutmẹ(relativelayouthiệntại)
FrameLayout
Làlayoutđượcdùngđểhiểnthịmộtviewbêntrong.ViewconcủaFramelayoutluônđượccănphíatrên,bêntráisovới
layoutmẹnày.Nếubạnthêmnhiềuhơn1viewvàobêntrongFrameLayout,thìcácviewnàysẽnằmchồnglênnhaunhư
vídụdướiđây.
android:id="@+id/RLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android=" />>
android:id="@+id/lblComments"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello,Android!"
ViewvàViewGroup
73
GiáotrìnhAndroid
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/lblComments"
android:layout_below="@+id/lblComments"
android:layout_centerHorizontal="true"
>
android:src="@drawable/droid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_width="124dp"
android:layout_height="wrap_content"
android:text="PrintPicture"/>
</FrameLayout>
</RelativeLayout>
ScrollView
ScrollViewlàmộtFrameLayoutđặcbiệt,chophépngườidùngcuộndọcmànhìnhkhinộidungbêntrongcủaScrollView
chiếmnhiềudiệntíchhơnviewmẹ.
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android=">
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true">
android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button1"/>
android:id="@+id/button2"
ViewvàViewGroup
74
GiáotrìnhAndroid
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button2"/>
android:id="@+id/button3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button3"/>
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="600dp"/>
android:id="@+id/button4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button4"/>
android:id="@+id/button5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button5"/>
</LinearLayout>
</ScrollView>
Trongvídụtrên,EditTextởgiữađượcđặtchiềucaolênđến600dpđểchắcchắnnóvượtquáchiềucaocủamànhình
điệnthoại,khiđókhichạytrênđiệnthoại/emulator,tasẽthấyviewcóthểcuộnlên,cuộnxuốngnhưhìnhvẽsau:
Hình:Scrollviewđangđượccuộnlên(trái)vàcuộnxuống(phải)
ViewvàViewGroup
75
GiáotrìnhAndroid
Thiếtkếgiaodiệnthíchnghivớihướngmànhình
Mộttínhnăngxuấthiệntrênhầuhếtcácđiệnthoạithôngminhhiệnhànhlàtínhnăngtựđộngthayđổihướnghiểnthịcủa
mànhìnhtừdọcsangnganghoặcngượclạikhingườidùngxoayđiệnthoạitheohướngtươngứng.Khôngngoạilệ,khi
thiếtbịAndroidthayđổihướngtừdọcsangnganghoặcngượclại,activityhiệntạisẽvẽlạicácviewconcủamìnhtheo
hướngmới,khiđóhàmonCreatecủaActivitysẽđượcgọilạitừđầu.Mặtkhác,dodiệntíchvàtỷlệvùnghiểnthịtheo
hướngdọcvàhướngngangkhácnhautươngđốinhiều,nênkhithiếtkếlayouttacầncóbiệnphápthíchhợpchosựthay
đổinày.
Có2phươngphápphổbiếnđểthiếtkếlayoutthíchnghivớisựthayđổinày:
Neo–neo(xếpcốđịnh)cácviewcontheocáccạnhcủamànhình.Đâylàcáchdễlàmnhất,khikíchthướcmànhình
thayđổi,vịtrícủacáclayoutconsẽđượcxếplạinhưngvẫncăntheocáccạnhgầnnhất.
Thayđổikíchthướcvàvịtrí–cáchlàmtốncôngvàlinhhoạthơnvàsắpxếplạitoànbộlayoutcủacácviewconkhi
cósựthayđổivềmànhình.Ngoài,racòncóthểthêm/bớtviewconvớinhữnghướngnhấtđịnh.
Tasẽxemvídụcụthểcho2phươngántrên.
Neocácviewcontheocáccạnhmànhình
<?xmlversion="1.0"encoding="utf-8"?>
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android=" />
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TopLeft"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TopRight"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"/>
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BottomLeft"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"/>
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BottomRight"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"/>
android:id="@+id/button5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Middle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
Trongvídụtrênbutton1đượcneotheogóctrênbêntrái,button2–góctrênbênphải,button3–gócdướibêntrái,
Bốcụcgiaodiệnthíchnghivớihướngmànhình
76
GiáotrìnhAndroid
button4–gócdướibênphải,button5–chínhgiữamànhình.Layouttrênkhihiểnthịtrênmànhìnhdọcvàngangsẽnhư
sau:
Hình:Neocácnútbấmtheocạnhmànhình-mànhìnhdọc
Hình:Neocácnútbấmtheocạnhmànhình-mànhìnhngang
Bốcụcgiaodiệnthíchnghivớihướngmànhình
77
GiáotrìnhAndroid
Thayđổikíchthướcvàvịtrí
Trongphươngphápnày,thôngthườngmỗihướngmànhìnhsẽcómộtlayoutriêng.Layoutnàycóthểđượccấuhình
trongcode,hoặcđặtfilelayoutvàothưmụccấuhìnhsẵnđểhệthốngtựlựachọntrongquátrìnhchạy.Đểtạolayoutriêng
choActivitytrêntheomànhìnhngang,tatạothưmụclayout-landtrongthưmụcres,sauđótạofilemain.xml(trùngtênvới
filelayouttrongthưmụcres/layout),vớinộidungnhưsau:
<?xmlversion="1.0"encoding="utf-8"?>
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android=" />
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TopLeft"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TopRight"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"/>
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BottomLeft"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"/>
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BottomRight"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"/>
android:id="@+id/button5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Middle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
android:id="@+id/button6"
android:layout_width="180px"
android:layout_height="wrap_content"
android:text="TopMiddle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"/>
android:id="@+id/button7"
android:layout_width="180px"
android:layout_height="wrap_content"
android:text="BottomMiddle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
Đểýtathấylayoutnàycó7nútthayvì5nútnhưlayoutmặcđịnh(chomànhìnhdọc).Kếtquảhiểnthịchomànhình
ngangsẽxuấthiệnthêm2nútbấmởtrênvàdướimànhình,căngiữatheochiềungangnhưhìnhdưới:
Bốcụcgiaodiệnthíchnghivớihướngmànhình
78
GiáotrìnhAndroid
Hình:Giaodiệntheomànhìnhngangvới2nútmớixuấthiện(TopMiddlevàBottomMiddle)
Ngoàirakhithayđổihướngmànhình,Activitysẽđượcvẽlạihoàntoàntừđầuvàtrạngtháihiệntạisẽmất,baogồmgiá
trịcủacáctrường,nộidungcủacácviewkhôngđượcđặttêntronglayout…Vìvậy,trongtrườnghợpcầnthiếtphảilưutrữ
trạngtháihiệntạicủaActivity,việctacầnlàmlànạpchồng2hàmsau:
@Override
publicvoidonSaveInstanceState(BundleoutState){
//---savewhateveryouneedtopersist--outState.putString("ID","1234567890");
super.onSaveInstanceState(outState);
}
@Override
publicvoidonRestoreInstanceState(BundlesavedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
//---retrievetheinformationpersistedearlier--StringID=savedInstanceState.getString("ID");
}
DữliệucầnlưutrữđượcchứatrongmộtđốitượngBundle,chitiếtvềđốitượngnàyvàcácloạidữliệucóthểlưutrữ
trongnóbạnđọctựtìmhiểuvàphầnnàyđượccoinhưbàitập.Trongvídụtrêntađãtiếnhànhlưuvàlấylạigiátrịcủa
mộtchuỗi(“0123456789”)vàoBundledướitênlà“ID”.
Điềukhiểnhướngcủamànhình
Trongmộtsốtrườnghợp,tacầnthiếtkếmộtsốActivitychỉhỗtrợmộtloạihướngmànhìnhcụthể.Vídụ,mànhìnhxem
phimcóthểđượcthiếtlậpchỉcóhướngnằmngang,haymànhìnhgọiđiệnthoạiđượcthiếtlậpluônluônhiểnthịtheo
chiềudọc.
Đểlàmviệcnày,tacóthểkhaibáothuộctínhcủaactivitytươngứngtrongfileManifesthoặccấuhìnhtrongmãnguồncủa
hàmonCreatetươngứngvớiActivitycầnthiếtlập.
Vídụvềcấuhìnhhướngmànhìnhluônnằmngangtrongmãnguồn:
Bốcụcgiaodiệnthíchnghivớihướngmànhình
79
GiáotrìnhAndroid
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//---changetolandscapemode--setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
VàtrongManifest:
android:label="@string/app_name"
android:name=".OrientationsActivity"
android:screenOrientation="landscape">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Bốcụcgiaodiệnthíchnghivớihướngmànhình
80
GiáotrìnhAndroid
Sửdụngtrìnhđơn(Menu)
Trìnhđơn(bảngchọn,menu)dùngđểhiểnthịcáchànhđộngthườngítdùnghơnvàkhônghiểnthịtrựctiếplênmànhình.
TrongAndroidcó2loạitrìnhđơn:
Trìnhđơnchính(Optionsmenu)–hiểnthịcáchànhđộngliênquanđếntoànbộActivityhiệntại.TrongAndroid,để
kíchhoạttrìnhđơnnày,tabấmnútMenucủathiếtbị(phímcứnghoặcphímảotrênmànhình)
Trìnhđơnngữcảnh(ContextMenu)–hiểnthịcáchànhđộngliênquanđếnmộtviewcụthểtrênmànhình,trìnhđơn
nàyđượckíchhoạtbằngcáchbấmvàgiữngóntay(longtap)trênviewtươngứng.
Hìnhdướiđâyminhhọatrìnhđơnchính(bêntrái)vàtrìnhđơnngữcảnhkhibấmvàgiữtaytrênảnh(bênphải)củaứng
dụngBrowser(trìnhduyệtweb):
Hình:Trìnhđơnchính(trái)vàtrìnhđơnngữcảnh(phải)
Vềmặtlậptrình,2loạimenunàysửdụngcùngmộtlớp(android.view.Menu)vàchứacácđốitượnggiốngnhau
(android.view.MenuItem).Vìvậytatạosẵn2phươngthứcdùngchungcho2loạimenunàyđểtạomenuvớicácmục
(item)bêntrongvàxửlýsựkiệnbấmvàotừngitemnhưdướiđây:
HàmCreateMenudùngđểthêm7mụcvàomenucósẵn(đượctruyềnvàodướiạngthamsố):
privatevoidCreateMenu(Menumenu)
{
menu.setQwertyMode(true);
MenuItemmnu1=menu.add(0,0,0,"Item1");
{
mnu1.setAlphabeticShortcut('a');
mnu1.setIcon(R.drawable.ic_launcher);
}
MenuItemmnu2=menu.add(0,1,1,"Item2");
Sửdụngtrìnhđơn(Menu)
81
GiáotrìnhAndroid
{
mnu2.setAlphabeticShortcut('b');
mnu2.setIcon(R.drawable.ic_launcher);
}
MenuItemmnu3=menu.add(0,2,2,"Item3");
{
mnu3.setAlphabeticShortcut('c');
mnu3.setIcon(R.drawable.ic_launcher);
}
MenuItemmnu4=menu.add(0,3,3,"Item4");
{
mnu4.setAlphabeticShortcut('d');
}
menu.add(0,4,4,"Item5");
menu.add(0,5,5,"Item6");
menu.add(0,6,6,"Item7");
}
HàmMenuChoiceđểxửlýsựkiệntươngứngvớitừngmụcđượclựachọn(truyềnvàodạngthamsố).Vớimụcđíchminh
họa,trongvídụsau,khimộtmụcđượcchọn,tachỉđơngiảnhiểnthịtêncủamụcđóbằngthôngbáodạngToast.
privatebooleanMenuChoice(MenuItemitem)
{
switch(item.getItemId()){
case0:
Toast.makeText(this,"YouclickedonItem1",
Toast.LENGTH_LONG).show();
returntrue;
case1:
Toast.makeText(this,"YouclickedonItem2",
Toast.LENGTH_LONG).show();
returntrue;
case2:
Toast.makeText(this,"YouclickedonItem3",
Toast.LENGTH_LONG).show();
returntrue;
case3:
Toast.makeText(this,"YouclickedonItem4",
Toast.LENGTH_LONG).show();
returntrue;
case4:
Toast.makeText(this,"YouclickedonItem5",
Toast.LENGTH_LONG).show();
returntrue;
case5:
Toast.makeText(this,"YouclickedonItem6",
Toast.LENGTH_LONG).show();
returntrue;
case6:
Toast.makeText(this,"YouclickedonItem7",
Toast.LENGTH_LONG).show();
returntrue;
}
returnfalse;
}
Trìnhđơnchính
Đểhiểnthịtrìnhđơnchính,tanạpchồnghàmonCreateOptionMenu(Menumenu)vàthêmcácmụcvàođốitượngmenu(trong
thamsốcủahàm):
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
super.onCreateOptionsMenu(menu);
CreateMenu(menu);
returntrue;
}
Sửdụngtrìnhđơn(Menu)
82
GiáotrìnhAndroid
Đểhiểnthịmenunàylúcchạyứngdụng,tabấmphímMENUcủathiếtbị.
Đểxửlýsựkiệnchọnmộtitemtrongmenuhiệnra,tacầnnạpchồnghàmonOptionsItemSelected(MenuItemitem):
@Override
publicbooleanonOptionsItemSelected(MenuItemitem)
{
returnMenuChoice(item);
}
HìnhbêndướiminhhọamenuchínhđượctạoởtrêntrongtrườnghợpthiếtlậpSDKnhỏnhấtđượchỗtrợtrong
AndroidManifest.xml>=10(<uses-sdkandroid:minSdkVersion=“10”/>-hìnhbêntrái)và<10(<usessdkandroid:minSdkVersion=“9”/>hìnhbênphải).
Hình:TrìnhđơnchínhvớiAPImức10(trái)vàAPImức9(phải)
Trìnhđơnngữcảnh
Đểhiểnthịtrìnhđơnngữcảnh,tanạpchồnghàmonCreateContextMenu(Menumenu)vàthêmcácmụcvàođốitượngmenu
(làthamsốcủahàm):
@Override
publicvoidonCreateContextMenu(ContextMenumenu,Viewview,
ContextMenuInfomenuInfo)
{
super.onCreateContextMenu(menu,view,menuInfo);
CreateMenu(menu);
}
Sửdụngtrìnhđơn(Menu)
83
GiáotrìnhAndroid
Đểxửlýsựkiệnchọnmộtitemtrongmenuhiệnra,tacầnnạpchồnghàmonContextItemSelected(MenuItemitem):
@Override
publicbooleanonContextItemSelected(MenuItemitem)
{
returnMenuChoice(item);
}
Đểgắnmenungữcảnhnàyvàonútbấmbutton1,tathêmđoạnmãsauvàohàmonCreatecủaactivity:
Buttonbtn=(Button)findViewById(R.id.button1);
btn.setOnCreateContextMenuListener(this);
Đểhiểnthịmenunàylúcchạyứngdụng,tabấmvàgiữngóntaylêntrênnútbấmbutton1,trìnhđơnhiệnranhưhình
bêndưới:
Hình:Trìnhđơnngữcảnhxuấthiệnkhibấmvàgiữngóntaytrênnútbấmbutton1
Sửdụngtrìnhđơn(Menu)
84
GiáotrìnhAndroid
Sửdụngthanhtácvụ(ActionBar)
CùngvớiFragment,mộttínhnăngmớiđượcgiớithiệutừAndroid3.0HoneyComblàthanhtácvụbêntrongứngdụng
(ActionBar)đểthaythếchothanhtiêuđềcũ.ActionbarbaogồmiconcủaứngdụngvàtiêuđềcủaActivityởbêntrái.
Ngoàira,ngườidùngcóthểđặtởbênphảicácnútbấmđặcbiệt,gọilàactionitem.Hìnhbêndướiminhhọaactionbar
củaứngdụngemailtrongAndroidvớiiconứngdụng,tiêuđềemailvà4actionitemởbênphải:
Hình:ActionBarvớitiêuđềvàcácnútbấm
ActionBardùngchungmenuchính(optionmenu)nhưmôtảtrongphầntrước.Đểcácmenuitemtrongmenuchínhhiển
thịtrênActionbardướidạngcácactionitem,tachỉcầngọihàmmnu1.setShowAsAction()củamỗimenuitem.
privatevoidCreateMenu(Menumenu)
{
MenuItemmnu1=menu.add(0,0,0,"Item1");
{
mnu1.setIcon(R.drawable.ic_launcher);
mnu1.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM|
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
MenuItemmnu2=menu.add(0,1,1,"Item2");
{
mnu2.setIcon(R.drawable.ic_launcher);
mnu2.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM|
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
MenuItemmnu3=menu.add(0,2,2,"Item3");
{
mnu3.setIcon(R.drawable.ic_launcher);
mnu3.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM|
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
Sửdụngthanhtácvụ(ActionBar)
85
GiáotrìnhAndroid
}
MenuItemmnu4=menu.add(0,3,3,"Item4");
{
mnu4.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM|
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
MenuItemmnu5=menu.add(0,4,4,"Item5");
{
mnu5.setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM|
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
}
Kếtquảkhichạytrênthiếtbịnhưhìnhbêndưới.Đốivớimànhìnhdọc,cóítdiệntíchđểhiểnthịactionitemhơn(2cái),3
itemcònlạisẽhiểnthịdướidạngtrìnhđơnchínhnhưbìnhthường:
Hình:ActionBarvới2nútbấmkhimànhìnhdọc
Đốivớimànhìnhngang,nhiềuitemđượchiểnthịdướidạngactionitemhơn(4cái):
Sửdụngthanhtácvụ(ActionBar)
86
GiáotrìnhAndroid
Hình:ActionBarvới4nútbấmkhimànhìnhngang
Sửdụngthanhtácvụ(ActionBar)
87
GiáotrìnhAndroid
Xửlýsựkiệntươngtácvớicácthànhphầnđồhọa
NgườidùngtươngtácvớigiaodiệnđồhọacủaứngdụngAndroidtheo2mức:mứcActivityvàmứcView.ỞmứcActivity,
lớpActivitycầnnạpchồngcácphươngthứctươngứngđượcđịnhnghĩasẵn.Mộtsốphươngthứcnhưvậycóthểkểđến
như:
onKeyDown–đượcgọikhimộtphímđượcnhấnxuốngvàsựkiệnnàychưađượcxửlýbởibấtcứviewconnàotrong
activty
onKeyUp–đượcgọikhimộtphímđượcnhảravàsựkiệnnàychưađượcxửlýbởibấtcứviewconnàotrongactivty
onMenuItemSelected–đượcgọikhingườidùnglựachọnmộtitemtrongmenuđangđượcmởra
onMenuOpened–đượcgọikhimộttrìnhđơnđượcmởra.
NạpchồnghàmxửlýsựkiệncủaActivity
Vídụ:
@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent)
{
switch(keyCode)
{
caseKeyEvent.KEYCODE_DPAD_CENTER:
Toast.makeText(getBaseContext(),
"Centerwasclicked",
Toast.LENGTH_LONG).show();
break;
caseKeyEvent.KEYCODE_DPAD_LEFT:
Toast.makeText(getBaseContext(),
"Leftarrowwasclicked",
Toast.LENGTH_LONG).show();
break;
caseKeyEvent.KEYCODE_DPAD_RIGHT:
Toast.makeText(getBaseContext(),
"Rightarrowwasclicked",
Toast.LENGTH_LONG).show();
break;
caseKeyEvent.KEYCODE_DPAD_UP:
Toast.makeText(getBaseContext(),
"Uparrowwasclicked",
Toast.LENGTH_LONG).show();
break;
caseKeyEvent.KEYCODE_DPAD_DOWN:
Toast.makeText(getBaseContext(),
"Downarrowwasclicked",
Toast.LENGTH_LONG).show();
break;
}
returnfalse;
}
ĐăngkýsựkiệnchotừngView
MỗiviewtrongAndroidcóthểsinhracácsựkiệnkhingườidùngtácđộnglênnó.VídụnútbấmsinhrasựkiệnonClick
khingườidùngbấmvàonó,EditTextsinhrasựkiệnonFocusChangekhinhậnfocus(ngườidùngbấmvàoônhậpliệunày)
hoặcmấtfocus(khiviewkhácnhậnfocus).
Đểđăngkýsựkiệntươngtácvớicácview,tacóthểsửdụng“lớpẩndanh”(anonymousclass)nhưvídụdướiđây:
Buttonbtn1=(Button)findViewById(R.id.btn1);
btn1.setOnClickListener(btnListener);
Xửlýsựkiệntươngtácvớicácthànhphầnđồhọa
88
GiáotrìnhAndroid
và:
//---createananonymousclasstoactasabuttonclicklistener--privateOnClickListenerbtnListener=newOnClickListener()
{
publicvoidonClick(Viewv)
{
Toast.makeText(getBaseContext(),
((Button)v).getText()+"wasclicked",
Toast.LENGTH_LONG).show();
}
};
Hoặcsửdụnghàmnộibộẩndanh(anonymousinnerclass)nhưsau:
//---createananonymousinnerclasstoactasanonfocuslistener--EditTexttxt1=(EditText)findViewById(R.id.txt1);
txt1.setOnFocusChangeListener(newView.OnFocusChangeListener()
{
@Override
publicvoidonFocusChange(Viewv,booleanhasFocus){
Toast.makeText(getBaseContext(),
((EditText)v).getId()+"hasfocus-"+hasFocus,
Toast.LENGTH_LONG).show();
}
});
Xửlýsựkiệntươngtácvớicácthànhphầnđồhọa
89