【移動應(yīng)用開發(fā)技術(shù)】9102年末我對Android view的13條認(rèn)識_第1頁
【移動應(yīng)用開發(fā)技術(shù)】9102年末我對Android view的13條認(rèn)識_第2頁
【移動應(yīng)用開發(fā)技術(shù)】9102年末我對Android view的13條認(rèn)識_第3頁
【移動應(yīng)用開發(fā)技術(shù)】9102年末我對Android view的13條認(rèn)識_第4頁
【移動應(yīng)用開發(fā)技術(shù)】9102年末我對Android view的13條認(rèn)識_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余2頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】9102年末,我對Androidview的13條認(rèn)識

每次到每一年的年底,都會花幾天時間把今年對每個知識點總結(jié)一下。算是對自己經(jīng)驗的累積,以彌補(bǔ)自己的不足。把知識點匯總一下,看看自身的不足和錯誤,以便2020年再接再厲

每次到每一年的年底,都會花幾天時間把今年對每個知識點總結(jié)一下。算是對自己經(jīng)驗的累積,以彌補(bǔ)自己的不足。把知識點匯總一下,看看自身的不足和錯誤,以便2020年再接再厲(順手留下GitHub鏈接,需要獲取相關(guān)面試等內(nèi)容的可以自己去找)/xiangjiana/Android-MS(VX:m參考答案View的工作流程主要是指measure、layout、draw這三大流程,即測量、布局和繪制,其中measure確定View的測量寬//高,layout確定View的最終寬//高和四個頂點的位置,而draw則將View繪制到屏幕上View的繪制過程遵循如下幾步:點擊事件產(chǎn)生后,首先傳遞給Activity的dispatchTouchEvent方法,通過PhoneWindow傳遞給DecorView,然后再傳遞給根ViewGroup,進(jìn)入ViewGroup的dispatchTouchEvent方法,執(zhí)行onInterceptTouchEvent方法判斷是否攔截,再不攔截的情況下,此時會遍歷ViewGroup的子元素,進(jìn)入子View的dispatchToucnEvent方法,如果子view設(shè)置了onTouchListener,就執(zhí)行onTouch方法,并根據(jù)onTouch的返回值為true還是false來決定是否執(zhí)行onTouchEvent方法,如果是false則繼續(xù)執(zhí)行onTouchEvent。在onTouchEvent的ActionUp事件中判斷,如果設(shè)置了onClickListener,就執(zhí)行onClick方法。View事件傳遞分發(fā)機(jī)制?參考回答:View隨著Activity的創(chuàng)建而加載,startActivity啟動一個Activity時,在ActivityThread的handleLaunchActivity方法中會執(zhí)行Activity的onCreate方法,這個時候會調(diào)用setContentView加載布局創(chuàng)建出DecorView并將我們的layout加載到DecorView中,當(dāng)執(zhí)行到handleResumeActivity時,Activity的onResume方法被調(diào)用,然后WindowManager會將DecorView設(shè)置給ViewRootImpl,這樣,DecorView就被加載到Window中了,此時界面還沒有顯示出來,還需要經(jīng)過View的measure,layout和draw方法,才能完成View的工作流程。我們需要知道View的繪制是由ViewRoot來負(fù)責(zé)的,每一個DecorView都有一個與之關(guān)聯(lián)的ViewRoot,這種關(guān)聯(lián)關(guān)系是由WindowManager維護(hù)的,將DecorView和ViewRoot關(guān)聯(lián)之后,ViewRootImpl的requestLayout會被調(diào)用以完成初步布局,通過scheduleTraversals方法向主線程發(fā)送消息請求遍歷,最終調(diào)用ViewRootImpl的performTraversals方法,這個方法會執(zhí)行View的measurelayout和draw流程1.讓view支持wrap_content屬性,在onMeasure方法中針對AT_MOST模式做專門處理,否則wrap_content會和match_parent效果一樣(繼承ViewGroup也同樣要在onMeasure中做這個判斷處理)if(widthMeasureSpec==MeasureSpec.AT_MOST&&heightMeasureSpec==MeasureSpec.AT_MOST){

setMeasuredDimension(200,200);

//wrap_content情況下要設(shè)置一個默認(rèn)值,200只是舉個例子,最終的值需要計算得到剛好包裹內(nèi)容的寬高值}elseif(widthMeasureSpec==MeasureSpec.AT_MOST){

setMeasuredDimension(200,heightMeasureSpec);

}elseif(heightMeasureSpec==MeasureSpec.AT_MOST){

setMeasuredDimension(heightMeasureSpec,200);

}2.讓view支持padding(onDraw的時候,寬高減去padding值,margin由父布局控制,不需要view考慮),自定義ViewGroup需要考慮自身的padding和子view的margin造成的影響3.在view中盡量不要使用handler,使用view本身的post方法4.在onDetachedFromWindow中及時停止線程或動畫5.view帶有滑動嵌套情形時,處理好滑動沖突在上邊的分析中我們知道,View繪制流程的入口在ViewRootImpl的performTraversals方法,在方法中首先調(diào)用performMeasure方法,傳入一個childWidthMeasureSpec和childHeightMeasureSpec參數(shù),這兩個參數(shù)代表的是DecorView的MeasureSpec值,這個MeasureSpec值由窗口的尺寸和DecorView的LayoutParams決定,最終調(diào)用View的measure方法進(jìn)入測量流程measure:View的measure過程由ViewGroup傳遞而來,在調(diào)用View.measure方法之前,會首先根據(jù)View自身的LayoutParams和父布局的MeasureSpec確定子view的MeasureSpec,然后將view寬高對應(yīng)的measureSpec傳遞到measure方法中,那么子view的MeasureSpec獲取規(guī)則是怎樣的?分幾種情況進(jìn)行說明a.子view寬或高是個確定值,那么子view的size就是這個確定值,mode是EXACTLY(是不是說子view寬高可以超過父view?見下一個)b.子view寬或高設(shè)置為match_parent,那么子view的size就是占滿父容器剩余空間,模式就是EXACTLYc.子view寬或高設(shè)置為wrap_content,那么子view的size就是占滿父容器剩余空間,不能超過父容器大小,模式就是AT_MOSTa.子view寬或高是個確定值,那么子view的size就是這個確定值,mode是EXACTLYb.子view寬或高設(shè)置為match_parent,那么子view的size就是占滿父容器剩余空間,不能超過父容器大小,模式就是AT_MOSTc.子view寬或高設(shè)置為wrap_content,那么子view的size就是占滿父容器剩余空間,不能超過父容器大小,模式就是AT_MOSTa.子view寬或高是個確定值,那么子view的size就是這個確定值,mode是EXACTLYb.子view寬或高設(shè)置為match_parent,那么子view的size就是0,模式就是UNSPECIFIEDc.子view寬或高設(shè)置為wrap_content,那么子view的size就是0,模式就是UNSPECIFIED獲取到寬高的MeasureSpec后,傳入view的measure方法中來確定view的寬高,這個時候還要分情況

1.當(dāng)MeasureSpec的mode是UNSPECIFIED,此時view的寬或者高要看view有沒有設(shè)置背景,如果沒有設(shè)置背景,就返回設(shè)置的minWidth或minHeight,這兩個值如果沒有設(shè)置默認(rèn)就是0,如果view設(shè)置了背景,就取minWidth或minHeight和背景這個drawable固有寬或者高中的最大值返回2.當(dāng)MeasureSpec的mode是AT_MOST和EXACTLY,此時view的寬高都返回從MeasureSpec中獲取到的size值,這個值的確定見上邊的分析。因此如果要通過繼承view實現(xiàn)自定義view,一定要重寫onMeasure方法對wrap_conten屬性做處理,否則,他的match_parent和wrap_content屬性效果就是一樣的

1.當(dāng)MeasureSpec的mode是UNSPECIFIED,此時view的寬或者高要看view有沒有設(shè)置背景,如果沒有設(shè)置背景,就返回設(shè)置的minWidth或minHeight,這兩個值如果沒有設(shè)置默認(rèn)就是0,如果view設(shè)置了背景,就取minWidth或minHeight和背景這個drawable固有寬或者高中的最大值返回2.當(dāng)MeasureSpec的mode是AT_MOST和EXACTLY,此時view的寬高都返回從MeasureSpec中獲取到的size值,這個值的確定見上邊的分析。因此如果要通過繼承view實現(xiàn)自定義view,一定要重寫onMeasure方法對wrap_conten屬性做處理,否則,他的match_parent和wrap_content屬性效果就是一樣的layout:layout方法的作用是用來確定view本身的位置,onLayout方法用來確定所有子元素的位置,當(dāng)ViewGroup的位置確定之后,它在onLayout中會遍歷所有的子元素并調(diào)用其layout方法,在子元素的layout方法中onLayout方法又會被調(diào)用。layout方法的流程是,首先通過setFrame方法確定view四個頂點的位置,然后view在父容器中的位置也就確定了,接著會調(diào)用onLayout方法,確定子元素的位置,onLayout是個空方法,需要繼承者去實現(xiàn)。getMeasuredHeight和getHeight方法有什么區(qū)別?getMeasuredHeight(測量高度)形成于view的measure過程,getHeight(最終高度)形成于layout過程,在有些情況下,view需要measure多次才能確定測量寬高,在前幾次的測量過程中,得出的測量寬高有可能和最終寬高不一致,但是最終來說,還是會相同,有一種情況會導(dǎo)致兩者值不一樣,如下,此代碼會導(dǎo)致view的最終寬高比測量寬高大100PXpublicvoidlayout(intl,intt,intr,intb){

super.layout(l,t,r+100,b+100);{

}View的繪制過程遵循如下幾步:

a.繪制背景background.draw(canvas)b.繪制自己(onDraw)c.繪制children(dispatchDraw)d.繪制裝飾(onDrawScrollBars)

a.繪制背景background.draw(canvas)b.繪制自己(onDraw)c.繪制children(dispatchDraw)d.繪制裝飾(onDrawScrollBars)View繪制過程的傳遞是通過dispatchDraw來實現(xiàn)的,它會遍歷所有的子元素的draw方法,如此draw事件就一層一層的傳遞下去了ps:view有一個特殊的方法setWillNotDraw,如果一個view不需要繪制內(nèi)容,即不需要重寫onDraw方法繪制,可以開啟這個標(biāo)記,系統(tǒng)會進(jìn)行相應(yīng)的優(yōu)化。默認(rèn)情況下,View沒有開啟這個標(biāo)記,默認(rèn)認(rèn)為需要實現(xiàn)onDraw方法繪制,當(dāng)我們繼承ViewGroup實現(xiàn)自定義控件,并且明確知道不需要具備繪制功能時,可以開啟這個標(biāo)記,如果我們重寫了onDraw,那么要顯示的關(guān)閉這個標(biāo)記子view寬高可以超過父view?能

1.android:clipChildren="false"這個屬性要設(shè)置在父view上。代表其中的子View可以超出屏幕。2.子view要有具體的大小,一定要比父view大才能超出。比如父view高度100px子view設(shè)置高度150px。子view比父view大,這樣超出的屬性才有意義。(高度可以在代碼中動態(tài)賦值,但不能用wrap_content/match_partent)。3.對父布局還有要求,要求使用linearLayout(反正我用RelativeLayout是不行)。你如果必須用其他布局可以在需要超出的view上面套一個linearLayout外面再套其他的布局。4.最外面的布局如果設(shè)置的padding不能超出

1.android:clipChildren="false"這個屬性要設(shè)置在父view上。代表其中的子View可以超出屏幕。2.子view要有具體的大小,一定要比父view大才能超出。比如父view高度100px子view設(shè)置高度150px。子view比父view大,這樣超出的屬性才有意義。(高度可以在代碼中動態(tài)賦值,但不能用wrap_content/match_partent)。3.對父布局還有要求,要求使用linearLayout(反正我用RelativeLayout是不行)。你如果必須用其他布局可以在需要超出的view上面套一個linearLayout外面再套其他的布局。4.最外面的布局如果設(shè)置的padding不能超出參考回答:MotionEvent是手指接觸屏幕后所產(chǎn)生的一系列事件。典型的事件類型有如下:

ACTION_DOWN:手指剛接觸屏幕ACTION_MOVE:手指在屏幕上移動ACTION_UP:手指從屏幕上松開的一瞬間ACTION_CANCELL:手指保持按下操作,并從當(dāng)前控件轉(zhuǎn)移到外層控件時觸發(fā)

ACTION_DOWN:手指剛接觸屏幕ACTION_MOVE:手指在屏幕上移動ACTION_UP:手指從屏幕上松開的一瞬間ACTION_CANCELL:手指保持按下操作,并從當(dāng)前控件轉(zhuǎn)移到外層控件時觸發(fā)正常情況下,一次手指觸摸屏幕的行為會觸發(fā)一系列點擊事件,考慮如下幾種情況:

點擊屏幕后松開,事件序列:DOWN→UP點擊屏幕滑動一會再松開,事件序列為DOWN→MOVE→→MOVE→UP

點擊屏幕后松開,事件序列:DOWN→UP點擊屏幕滑動一會再松開,事件序列為DOWN→MOVE→→MOVE→UP參考回答:常見開發(fā)中事件沖突的有ScrollView與RecyclerView的滑動沖突、RecyclerView內(nèi)嵌同時滑動同一方向滑動沖突的處理規(guī)則:滑動沖突的實現(xiàn)方法:參考回答:invalidate()與postInvalidate()都用于刷新View,主要

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論