面試寶典|Android基礎(chǔ)(三)

本篇主要講解View及Drawable相關(guān)

View相關(guān)

Q:MotionEvent是什么?包含幾種事件?什么條件下會產(chǎn)生?

  • 技術(shù)點:View觸控
  • 參考回答::MotionEvent是手指觸摸屏幕鎖產(chǎn)生的一系列事件。包含的事件有:
    • ACTION_DOWN:手指剛接觸屏幕
    • ACTION_MOVE:手指在屏幕上滑動
    • ACTION_UP:手指在屏幕上松開的一瞬間
    • ACTION_CANCEL:手指保持按下操作,并從當(dāng)前控件轉(zhuǎn)移到外層控件時會觸發(fā)

Q:scrollTo()和scrollBy()的區(qū)別?

  • 技術(shù)點:View滑動
  • 參考回答:scrollBy內(nèi)部調(diào)用了scrollTo,它是基于當(dāng)前位置的相對滑動;而scrollTo是絕對滑動,因此如果利用相同輸入?yún)?shù)多次調(diào)用scrollTo()方法,由于View初始位置是不變只會出現(xiàn)一次View滾動的效果而不是多次。
  • 引申:兩者都只能對view內(nèi)容進(jìn)行滑動,而不能使view本身滑動,且非平滑,可使用Scroller有過渡滑動的效果

Q:Scroller中最重要的兩個方法是什么?主要目的是?

  • 技術(shù)點:View滑動
  • 思路:從Scroller實現(xiàn)滑動的具體過程出發(fā)
  • 參考回答:Scroller實現(xiàn)滑動的具體過程:
    • 在MotionEvent.ACTION_UP事件觸發(fā)時調(diào)用startScroll()方法,該方法并沒有進(jìn)行實際的滑動操作,而是記錄滑動相關(guān)量
    • 馬上調(diào)用invalidate/postInvalidate()方法,請求View重繪,導(dǎo)致View.draw方法被執(zhí)行
    • 緊接著會調(diào)用View.computeScroll()方法,此方法是空實現(xiàn),需要自己處理邏輯。具體邏輯是:先判斷computeScrollOffset(),若為true(表示滾動未結(jié)束),則執(zhí)行scrollTo()方法,它會再次調(diào)用postInvalidate(),如此反復(fù)執(zhí)行,直到返回值為false。流程圖如下:


      View滑動流程圖

      其中,最重要的兩個方法是startScroll()和computeScroll()

Q:談一談View的事件分發(fā)機制?

  • 技術(shù)點:View事件分發(fā)
  • 思路:從分發(fā)本質(zhì)、傳遞順序、核心方法展開
  • 參考回答:
    • 事件分發(fā)本質(zhì):就是對MotionEvent事件分發(fā)的過程。即當(dāng)一個MotionEvent產(chǎn)生了以后,系統(tǒng)需要將這個點擊事件傳遞到一個具體的View上。
    • 點擊事件的傳遞順序:Activity(Window) -> ViewGroup -> View
    • 三個主要方法:
      • dispatchTouchEvent:進(jìn)行事件的分發(fā)(傳遞)。返回值是 boolean 類型,受當(dāng)前onTouchEvent和下級view的dispatchTouchEvent影響
      • onInterceptTouchEvent:對事件進(jìn)行攔截。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的。一旦攔截,則執(zhí)行ViewGroup的onTouchEvent,在ViewGroup中處理事件,而不接著分發(fā)給View。且只調(diào)用一次,所以后面的事件都會交給ViewGroup處理。
      • onTouchEvent:進(jìn)行事件處理。

Q:如何解決View的滑動沖突?

  • 技術(shù)點:View滑動沖突
  • 思路:從處理規(guī)則和具體實現(xiàn)方法展開討論
  • 參考回答:
    • (1)處理規(guī)則:
      • 對于由于外部滑動和內(nèi)部滑動方向不一致導(dǎo)致的滑動沖突,可以根據(jù)滑動的方向判斷誰來攔截事件。
      • 對于由于外部滑動方向和內(nèi)部滑動方向一致導(dǎo)致的滑動沖突,可以根據(jù)業(yè)務(wù)需求,規(guī)定何時讓外部View攔截事件何時由內(nèi)部View攔截事件。
      • 對于上面兩種情況的嵌套,相對復(fù)雜,可同樣根據(jù)需求在業(yè)務(wù)上找到突破點。
    • (2)實現(xiàn)方法:
      • 外部攔截法:指點擊事件都先經(jīng)過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截。具體方法:需要重寫父容器的onInterceptTouchEvent方法,在內(nèi)部做出相應(yīng)的攔截。
      • 內(nèi)部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進(jìn)行處理。具體方法:需要配合requestDisallowInterceptTouchEvent方法。

Q:談一談View的工作原理?

  • 技術(shù)點:View工作流程
  • 思路:圍繞三大流程展開
  • 參考回答:View工作流程簡單來說就是,先measure測量,用于確定View的測量寬高,再 layout布局,用于確定View的最終寬高和四個頂點的位置,最后 draw繪制,用于將View 繪制到屏幕上。具體過程圖見:


    View的繪制流程
    • ViewRoot對應(yīng)于ViewRootImpl類,它是連接WindowManager和DecorView的紐帶。
    • View的繪制流程是從ViewRoot和performTraversals開始。
    • performTraversals()依次調(diào)用performMeasure()、performLayout()和performDraw()三個方法,分別完成頂級 View的繪制。
    • 其中,performMeasure()會調(diào)用measure(),measure()中又調(diào)用onMeasure(),實現(xiàn)對其所有子元素的measure過程,這樣就完成了一次measure過程;接著子元素會重復(fù)父容器的measure過程,如此反復(fù)至完成整個View樹的遍歷。layout和draw同理。

Q:MeasureSpec是什么?有什么作用?

  • 技術(shù)點:View工作流程(measure)
  • 思路:從MeasureSpec作用、組成、模式和決定因素展開
  • 參考回答:
    • 作用:通過寬測量值widthMeasureSpec和高測量值heightMeasureSpec決定View的大小
    • 組成:一個32位int值,高2位代表SpecMode(測量模式),低30位代表SpecSize( 某種測量模式下的規(guī)格大小)。
    • 三種模式:
      • UNSPECIFIED:父容器不對View有任何限制,要多大有多大。常用于系統(tǒng)內(nèi)部。
      • EXACTLY(精確模式):父視圖為子視圖指定一個確切的尺寸SpecSize。對應(yīng)LayoutParams中的match_parent或具體數(shù)值。
      • AT_MOST(最大模式):父容器為子視圖指定一個最大尺寸SpecSize,View的大小不能大于這個值。對應(yīng)LayoutParams中的wrap_content。
    • 決定因素:值由子View的布局參數(shù)LayoutParams和父容器的MeasureSpec值共同決定。具體規(guī)則見下圖:


  • 引申:直接繼承View的自定義View需要重寫onMeasure()并設(shè)置wrap_content時的自身大小,否則效果相當(dāng)于macth_parent

Q:自定義View/ViewGroup需要注意什么?

  • 技術(shù)點:自定義View
  • 參考回答:


Q:onTouch()、onTouchEvent()和onClick()關(guān)系?

  • 技術(shù)點:View事件分發(fā)
  • 參考回答:優(yōu)先度onTouch()>onTouchEvent()>onClick()。因此onTouchListener的onTouch()方法會先觸發(fā);如果onTouch()返回false才會接著觸發(fā)onTouchEvent(),同樣的,內(nèi)置諸如onClick()事件的實現(xiàn)等等都基于onTouchEvent();如果onTouch()返回true,這些事件將不會被觸發(fā)。
  • 引申:OnTouchListener、OnClickListener的沖突

Q:SurfaceView和View的區(qū)別?

  • 技術(shù)點:View、SurfaceView
  • 參考回答:SurfaceView是從View基類中派生出來的顯示類,他和View的區(qū)別有:
    • View需要在UI線程對畫面進(jìn)行刷新,而SurfaceView可在子線程進(jìn)行頁面的刷新
    • View適用于主動更新的情況,而SurfaceView適用于被動更新,如頻繁刷新,這是因為如果使用View頻繁刷新會阻塞主線程,導(dǎo)致界面卡頓
    • SurfaceView在底層已實現(xiàn)雙緩沖機制,而View沒有,因此SurfaceView更適用于需要頻繁刷新、刷新時數(shù)據(jù)處理量很大的頁面

Q:invalidate()和postInvalidate()的區(qū)別?

  • 技術(shù)點:View刷新
  • 參考回答:invalidate()與postInvalidate()都用于刷新View,主要區(qū)別是invalidate()在主線程中調(diào)用,若在子線程中使用需要配合handler;而postInvalidate()可在子線程中直接調(diào)用。

Drawable相關(guān)

Q:了解哪些Drawable?適用場景?

  • 技術(shù)點:res資源
  • 參考回答:BitmapDrawable表示一張圖片、NinePatchDrawable可自動地根據(jù)所需的寬/高對圖片進(jìn)行相應(yīng)的縮放并保證不失真、ShapeDrawable表示純色、有漸變效果的基礎(chǔ)幾何圖形、StateListDrawable表示一個Drawable的集合且每個Drawable對應(yīng)著View的一種狀態(tài)、LayerDrawable可通過將不同的Drawable放置在不同的層上面從而達(dá)到一種疊加后的效果

Q:mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和ldpi存在怎樣的關(guān)系?

  • 技術(shù)點:res資源
  • 參考回答:表示不同密度的圖片資源,像素從高到低依次排序為xxxhdpi>xxhdpi>xhdpi>hdpi>mdpi>ldpi,根據(jù)手機的dpi不同加載不同密度的圖片

Q:dp、dpi、px的區(qū)別?

  • 技術(shù)點:Android適配
  • 參考回答:
    • px:像素,如分辨率1920x1080表示高為1920個像素、寬為1080個像素
    • dpi:每英寸的像素點,如分辨率為1920x1080的手機尺寸為4.95英寸,則該手機DPI為(1920x1920+ 1080x1080)?/4.95≈445dpi
    • dp:密度無關(guān)像素,是個相對值

Q:res目錄和assets目錄的區(qū)別?

  • 技術(shù)點:res、assets
  • 參考回答:
    • res/raw中的文件會被映射到R.java文件中,訪問時可直接使用資源ID,不可以有目錄結(jié)構(gòu)
    • assets文件夾下的文件不會被映射到R.java中,訪問時需要AssetManager類,可以創(chuàng)建子文件夾
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容