《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 其他 > 設(shè)計(jì)應(yīng)用 > 深入理解Android 之界面構(gòu)造
深入理解Android 之界面構(gòu)造
Venus神廟的博客
摘要: 對(duì)于開(kāi)發(fā)者來(lái)說(shuō),,鍛造這樣的面容,,不但需要高超的技藝,也需要有稱(chēng)手的工具和對(duì)得起黨的料子。俗話說(shuō),,朽木不可雕也,,芙蓉不是一日煉成的,,不是什么平臺(tái)都能叫特能書(shū),。
關(guān)鍵詞: Android UI
Abstract:
Key words :

  UI" title="UI">UI界面,對(duì)于每個(gè)應(yīng)用而言,,是它與用戶進(jìn)行交互的門(mén)臉,。好的門(mén)臉,不只是是要亮麗可人,,最好還能秀色可餐過(guò)目不忘,,甚至還應(yīng)該有涵養(yǎng)有氣質(zhì),彬彬有理溫柔耐心,。

  對(duì)于開(kāi)發(fā)者來(lái)說(shuō),,鍛造這樣的面容,不但需要高超的技藝,,也需要有稱(chēng)手的工具和對(duì)得起黨的料子,。俗話說(shuō),朽木不可雕也,,芙蓉不是一日煉成的,,不是什么平臺(tái)都能叫特能書(shū)。有套好用的UI框架,,對(duì)于開(kāi)發(fā)者而言,,真有如沙漠中的甘露,而要是撞見(jiàn)了杯具的UI套件,,整個(gè)界面開(kāi)發(fā)就有如夢(mèng)魘了,。

  Android" title="Android">Android的UI框架,最核心的,,是資源和Layout體系,,然后,通過(guò)完善的控件庫(kù),,簡(jiǎn)明的接口設(shè)計(jì),,進(jìn)一步幫助開(kāi)發(fā)者,能夠最快的搭建自己需要界面(聽(tīng)到這里,,Symbian同學(xué)開(kāi)始鉆土。..)。

  UI控件

  做UI,,有時(shí)候就像搭積木,,在Android中,這個(gè)最原子的積木塊,,就是View,。所有其他的UI元素,都是派生于此類(lèi)的子孫類(lèi)們,。

  

  又從SDK中偷來(lái)張圖,,用來(lái)描述Android的UI控件結(jié)構(gòu),在每一個(gè)window下,,這都是一個(gè)標(biāo)準(zhǔn)而完整的樹(shù)結(jié)構(gòu),。View有一個(gè)子類(lèi)ViewGroup,它相當(dāng)于一個(gè)容器類(lèi)或者是復(fù)合控件,,所有派生與ViewGroup的子類(lèi)在這顆UI樹(shù)中都可以承擔(dān)著父節(jié)點(diǎn)的職責(zé),,而另一些繞過(guò)ViewGroup從View直通下來(lái)的,就只能蜷局在葉節(jié)點(diǎn)的范疇內(nèi)了,。

  之所有說(shuō)這是一個(gè)很標(biāo)準(zhǔn)的控件樹(shù),,是因?yàn)楦缚丶?duì)子控件有絕對(duì)的掌控權(quán),每個(gè)子控件的占地面積和位置,,都是基于父控件來(lái)分配的,,它能夠接受和處理的事件,也是父控件派發(fā)下去的,。這樣的結(jié)構(gòu),,被很多平臺(tái)和框架廣泛的認(rèn)可,和傳統(tǒng)的win開(kāi)發(fā)和杯具的Symbian相比,,雖然因?yàn)槭录鞑ネ緩阶冮L(zhǎng)了,,很多操作的效率變低了,但整個(gè)結(jié)構(gòu)更有層次性,,每個(gè)控件只需要多其父控件負(fù)責(zé)指揮子控件就好,,職責(zé)明確,邏輯簡(jiǎn)單,,利于開(kāi)發(fā)和設(shè)計(jì),。

  談及任何平臺(tái)的控件,都有一些不可避免的主題,,比如,,每個(gè)控件如何標(biāo)識(shí),如何設(shè)定大小和位置,,如何接受和處理事件,,如何繪制,,諸如此類(lèi)。

  標(biāo)識(shí)

  在Android中,,你可以為每個(gè)控件選擇設(shè)定一個(gè)id,,這個(gè)id的全局的唯一性不需要保證,但在某個(gè)局部的范圍內(nèi)具有可識(shí)別性,,這樣就可以通過(guò)這個(gè)id找到這個(gè)控件(如果不需要查找,,就別設(shè)置了。..),。

  但是,,在父控件中逐級(jí)的find比較,找到id匹配的控件,,然后再做轉(zhuǎn)型,,是一個(gè)比較重量的操作,于是Android又為控件憋出另一個(gè)屬性,,tag,。它接受任意object類(lèi)型的數(shù)據(jù),你可以把和這個(gè)控件對(duì)象相關(guān)的內(nèi)容堆在里面,。比如,,在list中,我們常常將和每個(gè)list item相關(guān)的所有控件元素封裝成一個(gè)object,,扔到tag中,,就不需要每次都去比較id進(jìn)行尋找,更加高效快捷,。

  尺寸

  在Android中,,控件最重要的大小屬性,就是width/height,,開(kāi)發(fā)者可以明確的指明控件的大小,,可以設(shè)定成為fill_parent和wrap_content,這樣的概念性的大小,。丈量并設(shè)定控件的位置,,是通過(guò)兩步來(lái)進(jìn)行的。

  第一步是measure,。它傳入此控件的width/height信息,,控件會(huì)根據(jù)自己的參數(shù),計(jì)算出真實(shí)需要的width/height,,然后調(diào)用setMeasuredDimension方法,,緩存成成員變量,留作后用,。

  在計(jì)算出大小之后,,會(huì)進(jìn)行另一個(gè)步驟,,layout。在這個(gè)過(guò)程中,,父控件會(huì)計(jì)算其上各個(gè)子控件的位置,,從而完成整個(gè)大小和位置的確定流程。整個(gè)measure和layout的流程,,都是自上到下,從樹(shù)頂往葉子來(lái)推進(jìn)的,。

  當(dāng)開(kāi)發(fā)人員需要自定義控件的時(shí)候,,可能需要關(guān)注這些內(nèi)容,通過(guò)重載onMeasure和onLayout方法,,可以定義自己控件的丈量方式,。

  事件

  在Android中,所有的按鍵,,觸屏等事件,,都是從頂至下進(jìn)行分發(fā)的。每個(gè)ViewGroup的對(duì)象,,會(huì)維系一個(gè)focused變量,,它表示在這個(gè)父控件中具備focus的控件,當(dāng)有按鍵時(shí)間發(fā)生的時(shí)候,,會(huì)找到這個(gè)focused子控件,,并傳遞給它。同理,,觸屏事件的分發(fā)也是類(lèi)似,,只不過(guò)和focus無(wú)關(guān),父控件會(huì)遍歷所有子控件,,看看誰(shuí)處于觸碰位置,,從而傳遞給誰(shuí)。

  另外還有一些事件,,邏輯上并不是從頂至下發(fā)起的,。比如,當(dāng)你修改某個(gè)子控件的內(nèi)容,,使得該子控件的大小和內(nèi)容都發(fā)生了變化,,就需要進(jìn)行控件的重排和重繪,這些操作不僅是子控件自己的事情,,需要整個(gè)控件樹(shù)上的所有控件都需要配合,。在Android中,處理這類(lèi)事情的實(shí)現(xiàn)策略是子控件維系一個(gè)ViewParent對(duì)象,,該對(duì)象象征著整個(gè)控件樹(shù)的管理者,,子控件產(chǎn)生影響整個(gè)控件樹(shù)的事件時(shí),,會(huì)通知到ViewParent,ViewParent會(huì)將其轉(zhuǎn)換成一個(gè)自頂向下的事件,,分發(fā)下去,。

  Android的事件處理邏輯,采用的是觀察者模式,。Android的控件提供了一些列的add/set Listener的接口,,使得外部觀察者,有機(jī)會(huì)處理控件事件,。比如,,你需要在某個(gè)button被點(diǎn)擊時(shí)做一些事情,你就需要派生一個(gè)View.OnClickListener對(duì)象作為觀察者,,調(diào)用該控件的setOnClickListener接口注冊(cè)進(jìn)去,,當(dāng)button被點(diǎn)擊,就可以獲得處理點(diǎn)擊事件的機(jī)會(huì)了,。當(dāng)然,,有的時(shí)候,你需要處理的邏輯更為復(fù)雜,,光是站在外面圍觀叫好不能解決問(wèn)題,,可能就需要派生某個(gè)控件,去重載onXXXX之類(lèi)的事件處理函數(shù),,進(jìn)行更完整的控制,。

  焦點(diǎn)

  對(duì)于一個(gè)非觸屏的機(jī)器,焦點(diǎn)的維系是一個(gè)極其重要的事情,,而在有觸屏的年代,,焦點(diǎn)的地位雖有所下降,但依然還是需要妥善保護(hù)的,。

  Android中,,是以控件樹(shù)為單位,來(lái)管理焦點(diǎn)的,。每個(gè)控件,,可以設(shè)置上下左右四向的focus轉(zhuǎn)移對(duì)象。當(dāng)在一個(gè)控件上發(fā)生焦點(diǎn)轉(zhuǎn)移事件,,Android會(huì)如前述,,自頂向下根據(jù)設(shè)定好的焦點(diǎn)轉(zhuǎn)移邏輯,跳轉(zhuǎn)到正確的控件上,。和Symbian相比,,真是,真是,。,。,。

  Layout

  Layout是一類(lèi)特殊的ViewGroup控件,它們本身沒(méi)有任何可顯示內(nèi)容,,形如透明的玻璃盒子,,存活的唯一理由,就是其中的內(nèi)部結(jié)構(gòu),,能夠更好的擺放它的子控件們,。

  比如線性的Layout,LinearLayout,。放入這個(gè)Layout的子控件,,會(huì)按水平或垂直方向,排排坐,,一個(gè)挨著一個(gè)按順序排列下去。TableLayout,,可以將子控件按照表格的形式,,一枚枚放置好。而RelativeLayout則更靈活,,可以設(shè)定各個(gè)控件之間的對(duì)齊和排列關(guān)系,,適合定制復(fù)雜的界面。

  有了Layout的存在,,控件和控件之間不再割裂的存在,,而是更有機(jī)的結(jié)合在了一起,設(shè)定起來(lái)也更為方便,。比Symbian那樣人肉維系各個(gè)控件的關(guān)系,,輕松自在多了。

  更多

  這些問(wèn)題的完整答案,,參見(jiàn)SDK中View的頁(yè)面:/reference/android/view/View.html,。

  實(shí)現(xiàn)

  有了這些對(duì)Android的UI控件的認(rèn)知,可以看更整體性的實(shí)現(xiàn)細(xì)節(jié),,那就是Activity的UI實(shí)現(xiàn),。

  

  如上圖所示,假設(shè)你做了個(gè)如同虛線框中結(jié)構(gòu)的一個(gè)界面,,通過(guò)Activity的setContentView方法,,塞進(jìn)了Activity中,就會(huì)形成圖示的一個(gè)邏輯關(guān)系,。每一個(gè)Activity,,都包含一個(gè)Window對(duì)象,它表示的是一個(gè)頂級(jí)的一整屏幕上面的界面邏輯,。在Android源碼中,,其實(shí)現(xiàn)是MidWindow,,它包含了一個(gè)FrameLayout對(duì)象,呈現(xiàn)出來(lái)就是那種帶著一個(gè)title的界面樣子,。自定義的一堆控件,,會(huì)插進(jìn)Window的界面部分,在Activity中,,所有事件的處理邏輯,,是Window先享用,沒(méi)消費(fèi)掉在交由這堆控件吃剩的,。

  在整個(gè)控件樹(shù)的最頂端,,是一個(gè)邏輯的樹(shù)頂,ViewParent,,在源碼中的實(shí)現(xiàn)是ViewRoot,。它是整個(gè)控件樹(shù)和WindowManager之間的事件信息的翻譯者。WindowManager是Android中一個(gè)重要的服務(wù),。它將用戶的操作,,翻譯成為指令,發(fā)送給呈現(xiàn)在界面上的各個(gè)Window,。Activity,,會(huì)將頂級(jí)的控件注冊(cè)到WindowManager中,當(dāng)用戶真是觸碰屏幕或鍵盤(pán)的時(shí)候,,WindowManager就會(huì)通知到,,而當(dāng)控件有一些請(qǐng)求產(chǎn)生,也會(huì)經(jīng)由ViewParent送回到WindowManager中,。從而完成整個(gè)通信流程,。

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載,。