導航:首頁 > 操作系統 > androidui元素

androidui元素

發布時間:2024-07-15 06:02:10

android UI繪制之View繪制的工作原理

這是AndroidUI繪制流程分析的第二篇文章,主要分析界面中View是如何繪制到界面上的具體過程。

ViewRoot 對應於 ViewRootImpl 類,它是連接 WindowManager 和 DecorView 的紐帶,View的三大流程均是通過 ViewRoot 來完成的。在 ActivityThread 中,當 Activity 對象被創建完畢後,會將 DecorView 添加到 Window 中,同時會創建 ViewRootImpl 對象,並將 ViewRootImpl 對象和 DecorView 建立關聯。

measure 過程決定了 View 的寬/高, Measure 完成以後,可以通過 getMeasuredWidth 和 getMeasuredHeight 方法來獲取 View 測量後的寬/高,在幾乎所有的情況下,它等同於View的最終的寬/高,但是特殊情況除外。 Layout 過程決定了 View 的四個頂點的坐標和實際的寬/高,完成以後,可以通過 getTop、getBottom、getLeft 和 getRight 來拿到View的四個頂點的位置,可以通過 getWidth 和 getHeight 方法拿到View的最終寬/高。 Draw 過程決定了 View 的顯示,只有 draw 方法完成後 View 的內容才能呈現在屏幕上。

DecorView 作為頂級 View ,一般情況下,它內部會包含一個豎直方向的 LinearLayout ,在這個 LinearLayout 裡面有上下兩個部分,上面是標題欄,下面是內容欄。在Activity中,我們通過 setContentView 所設置的布局文件其實就是被加到內容欄中的,而內容欄id為 content 。可以通過下面方法得到 content:ViewGroup content = findViewById(R.android.id.content) 。通過 content.getChildAt(0) 可以得到設置的 view 。 DecorView 其實是一個 FrameLayout , View 層的事件都先經過 DecorView ,然後才傳遞給我們的 View 。

MeasureSpec 代表一個32位的int值,高2位代表 SpecMode ,低30位代表 SpecSize , SpecMode 是指測量模式,而 SpecSize 是指在某種測量模式下的規格大小。
SpecMode 有三類,如下所示:

UNSPECIFIED

EXACTLY

AT_MOST

LayoutParams需要和父容器一起才能決定View的MeasureSpec,從而進一步決定View的寬/高。

對於頂級View,即DecorView和普通View來說,MeasureSpec的轉換過程略有不同。對於DecorView,其MeasureSpec由窗口的尺寸和其自身的LayoutParams共同確定;

對於普通View,其MeasureSpec由父容器的MeasureSpec和自身的Layoutparams共同決定;

MeasureSpec一旦確定,onMeasure就可以確定View的測量寬/高。

小結一下

當子 View 的寬高採用 wrap_content 時,不管父容器的模式是精確模式還是最大模式,子 View 的模式總是最大模式+父容器的剩餘空間。

View 的工作流程主要是指 measure 、 layout 、 draw 三大流程,即測量、布局、繪制。其中 measure 確定 View 的測量寬/高, layout 確定 view 的最終寬/高和四個頂點的位置,而 draw 則將 View 繪制在屏幕上。

measure 過程要分情況,如果只是一個原始的 view ,則通過 measure 方法就完成了其測量過程,如果是一個 ViewGroup ,除了完成自己的測量過程外,還會遍歷調用所有子元素的 measure 方法,各個子元素再遞歸去執行這個流程。

如果是一個原始的 View,那麼通過 measure 方法就完成了測量過程,在 measure 方法中會去調用 View 的 onMeasure 方法,View 類裡面定義了 onMeasure 方法的默認實現:

先看一下 getSuggestedMinimumWidth 和 getSuggestedMinimumHeight 方法的源碼

可以看到, getMinimumWidth 方法獲取的是 Drawable 的原始寬度。如果存在原始寬度(即滿足 intrinsicWidth > 0),那麼直接返回原始寬度即可;如果不存在原始寬度(即不滿足 intrinsicWidth > 0),那麼就返回 0。

接著看最重要的 getDefaultSize 方法:

如果 specMode 為 MeasureSpec.UNSPECIFIED 即未指定模式,那麼返回由方法參數傳遞過來的尺寸作為 View 的測量寬度和高度;
如果 specMode 不是 MeasureSpec.UNSPECIFIED 即是最大模式或者精確模式,那麼返回從 measureSpec 中取出的 specSize 作為 View 測量後的寬度和高度。

看一下剛才的表格:

當 specMode 為 EXACTLY 或者 AT_MOST 時,View 的布局參數為 wrap_content 或者 match_parent 時,給 View 的 specSize 都是 parentSize 。這會比建議的最小寬高要大。這是不符合我們的預期的。因為我們給 View 設置 wrap_content 是希望View的大小剛好可以包裹它的內容。

因此:

如果是一個 ViewGroup,除了完成自己的 measure 過程以外,還會遍歷去調用所有子元素的 measure 方法,各個子元素再遞歸去執行 measure 過程。

ViewGroup 並沒有重寫 View 的 onMeasure 方法,但是它提供了 measureChildren、measureChild、measureChildWithMargins 這幾個方法專門用於測量子元素。

如果是 View 的話,那麼在它的 layout 方法中就確定了自身的位置(具體來說是通過 setFrame 方法來設定 View 的四個頂點的位置,即初始化 mLeft , mRight , mTop , mBottom 這四個值), layout 過程就結束了。

如果是 ViewGroup 的話,那麼在它的 layout 方法中只是確定了 ViewGroup 自身的位置,要確定子元素的位置,就需要重寫 onLayout 方法;在 onLayout 方法中,會調用子元素的 layout 方法,子元素在它的 layout 方法中確定自己的位置,這樣一層一層地傳遞下去完成整個 View 樹的 layout 過程。

layout 方法的作用是確定 View 本身的位置,即設定 View 的四個頂點的位置,這樣就確定了 View 在父容器中的位置;
onLayout 方法的作用是父容器確定子元素的位置,這個方法在 View 中是空實現,因為 View 沒有子元素了,在 ViewGroup 中則進行抽象化,它的子類必須實現這個方法。

1.繪制背景( background.draw(canvas); );
2.繪制自己( onDraw );
3.繪制 children( dispatchDraw(canvas) );
4.繪制裝飾( onDrawScrollBars )。

dispatchDraw 方法的調用是在 onDraw 方法之後,也就是說,總是先繪制自己再繪制子 View 。

對於 View 類來說, dispatchDraw 方法是空實現的,對於 ViewGroup 類來說, dispatchDraw 方法是有具體實現的。

通過 dispatchDraw 來傳遞的。 dispatchDraw 會遍歷調用子元素的 draw 方法,如此 draw 事件就一層一層傳遞了下去。dispatchDraw 在 View 類中是空實現的,在 ViewGroup 類中是真正實現的。

如果一個 View 不需要繪制任何內容,那麼就設置這個標記為 true,系統會進行進一步的優化。

當創建的自定義控制項繼承於 ViewGroup 並且不具備繪制功能時,就可以開啟這個標記,便於系統進行後續的優化;當明確知道一個 ViewGroup 需要通過 onDraw 繪制內容時,需要關閉這個標記。

參考:《Android開發藝術探索》

② android鐨剈i鏄浠涔堟剰鎬濓紵

浠涔堟槸Android UI錛
Android UI鎸囩殑鏄疉ndroid緋葷粺涓鐨勭敤鎴風晫闈錛屽嵆鐢ㄦ埛鍦ㄤ嬌鐢ˋndroid璁懼囨椂鎵鐪嬪埌鐨勫悇縐嶇晫闈㈠拰浜や簰鏂瑰紡銆侫ndroid UI閲囩敤浜嗕竴縐嶇О涓衡淢aterial Design鈥濈殑璁捐¢庢牸錛屽叾涓鍖呮嫭浜嗚稿氬厓緔犲拰浜や簰鏂瑰紡錛屼緥濡傛寜閽銆佹枃鏈妗嗐佽彍鍗曘佸脊鍑烘嗙瓑絳夈傚紑鍙戜漢鍛樺彲榪愪笡鍜屼互浣跨敤Android鎻愪緵鐨凙PI鍜屽紑鍙戝伐鍏鋒潵鍒涘緩鑷宸辯殑鐢ㄦ埛鐣岄潰銆
Android UI鐨勭壒鐐
Android UI鐨勭壒鐐規槸澶氭牱鍖栧拰鍙瀹氬埗鍖栥侫ndroid寮鍙戣呭彲浠ヤ嬌鐢ㄥ悇縐嶅唴緗緇勪歡鍜岃嚜宸卞壋寤虹殑緇勪歡錛屽壋寤哄嚭鍚勭嶄笉鍚岄庢牸鍜屽艦鐘剁殑鐢ㄦ埛鐣岄潰銆備笌姝ゅ悓鏃訛紝寮鍙戣呬篃鍙浠ユ牴鎹鑷宸辯殑闇奼備慨鏀圭郴緇熻嚜甯︾殑緇勪歡錛屼互杈懼埌鏇村ソ鐨勭敤鎴蜂綋楠屻侫ndroid UI榪樻敮鎸佸氱偣瑙︽帶鍜屾墜鍔胯瘑鍒絳夐珮綰у姛鑳斤紝璁╃敤鎴蜂笌璁懼囩殑浜や簰鏇村姞鑷鐒跺拰鐩磋傘
Android UI鐨勯噸瑕佹
Android UI瀵逛簬鐢ㄦ埛浣撻獙闈炲父閲嶈併備竴涓浼樼鐨勭敤鎴風晫闈㈠彲浠ユ彁鍗囩敤鎴峰瑰簲鐢ㄧ殑鍠滅埍搴﹀拰浣跨敤浣撻獙錛岃屼竴涓緋熺硶鐨勭晫闈㈠垯浼氳╃敤鎴鋒劅鍒頒笉閫傜敋鑷蟲斁寮冧嬌鐢ㄣ傚洜姝ら儜鍜岋紝寮鍙戜漢鍛橀渶瑕佽姳璐瑰ぇ閲忕殑鏃墮棿鍜岀簿鍔涙潵涓鴻嚜宸辯殑搴旂敤璁捐″嚭浼橀泤鐨勭敤鎴風晫闈㈠拰嫻佺晠鐨勭敤鎴蜂綋楠屻傚悓鏃訛紝璋鋒瓕鍏鍙鎬篃榧撳姳鍜屾敮鏃佺洴鎸佸紑鍙戣呮瀯寤虹﹀悎Material Design瑙勮寖鐨勫簲鐢錛屼嬌寰楃敤鎴峰湪浣跨敤Android璁懼囨椂鑾峰緱鏇村ソ鐨勪綋楠屻

③ Android UI設計的基本元素有哪些

移動端的App界面,不論是iOS還是Android ,一般都由四個元素組成,分別是:狀態欄(status bar)、導航欄(navigation)、主菜單欄(submenu)、內容區域(content)。

狀態欄:主要用於顯示信號、運營商、電量等手機狀態的區域;
導航欄:主要顯示當前界面的名稱,包含相應的功能或者頁面間的跳轉按鈕;
主菜單欄:類似於頁面的主菜單,提供整個應用的分類內容的快速跳轉;
內容區域:展示應用提供的相應內容;

需要注意的一點就是,由於Android在4.0之後移除了實體鍵而使用屏幕下方的虛擬鍵,所以,Android將iOS中的主菜單從下方移動到了上方,從而避免誤操作虛擬鍵。

說到這里,就不得不說,雖然android和iOS都是移動端的操作系統,但是他們在UI設計還是存在很大的差異性。這是為什麼呢? 其實這基本上都是因為iOS的閉源導致的,由於它的商業化,導致很多設計被申請了專利,Android在很多地方都必須有所不同,說的最多的就是iOS的彈性滾動,其實Android的ScrollView要實現這樣的效果,只需要修改一個參數的值即可,但是由於這個效果iOS申請的專利,所以Android就無法使用了。

④ 如何獲取Android UI元素

appium android獲取元素方式:
1. 1.元素標簽(tagname) 通過UI的控制項類型ListtextFieldsList=driver.findElements(By.tagName( textfield ));
2. 元素的位置(xpath) 具有一核跡蔽定約束的路徑抽州祥象標示, 基於XPath方式改州;
3. 元素的值(name) driver.findElement(By.name( Save )).click();通過元素的文本, 標簽, 或者id標示;
4. 元素的IDdriver.findElement(By.id(com.example.android.contactmanager:id/contactNameEditText )).getText();

閱讀全文

與androidui元素相關的資料

熱點內容
題庫演算法 瀏覽:476
臨沂壓縮機生產廠家 瀏覽:942
cad旋轉角度命令 瀏覽:389
阿里雲是用什麼牌子伺服器 瀏覽:670
java基礎入門百度雲 瀏覽:979
360壓縮咋加密 瀏覽:354
hadoopmapreduce編程 瀏覽:302
linuxraid軟體 瀏覽:589
北美gre範文pdf 瀏覽:264
硬碟錄像機接什麼伺服器設備 瀏覽:502
智慧醫療方面最優演算法 瀏覽:920
伺服器ban掉了是什麼意思 瀏覽:394
vvo手機拍的視頻在哪個文件夾 瀏覽:838
華為防火牆cli命令手冊 瀏覽:895
於正新劇玉樓春在什麼App播放 瀏覽:127
學習社會經驗下載什麼app 瀏覽:475
php發布站程序 瀏覽:204
源碼編譯ntfs內核模塊 瀏覽:120
r11s手機管家沒有加密 瀏覽:781
怎麼看電腦連接哪個伺服器 瀏覽:191