日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

39、自定义控件(四)-- View源码分析

發布時間:2023/12/31 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 39、自定义控件(四)-- View源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、View源碼分析

ViewRoot對應于ViewRootImpl類,它是連接WindowManager和DecorView的紐帶,View的三大流程全是通過ViewRoot來完成的。

在ActivityThread中,當Activity對象被創建后,會將DectorView添加到Window中,同時會創建ViewRootImpl對象,并將

ViewRootImpl對象和decorView建立關聯,這個過程我們可以參看源碼:

root = new ViewRootImpl(view.getContext(),display); root.setView(view,wparams,panelparentView);

View的繪制流程是從ViewRoot的performTeaversals方法開始的,它經過measure、layout、draw三個過程才能最終將一個View繪制出來。

其中measure用來測量View的寬和高,layout用來確定View在父容器中放置的位置,而draw負責將View繪制在屏幕上。

針對performTraversals的大致流程:

如圖所示,performTraversals會依次調用performMeasure、performLayout和performDraw三個方法,分別完成頂級View的measure、layout和draw三大流程。

PperformMeasure會調用measure方法,measure方法又會調用onMeasure,其中onMeasure又會調用所有子元素的measure方法完成測量。

同理,performLayout和performDraw也是如此。

DecorView是頂級View,它其實是一個FrameLayout,View層的事件都先經過DecorView,然后才傳遞給我們的View。

1.1、Measure的原理

measure過程中,如果是View,則通過measure方法即可完成測量過程,如果是ViewGroup,則需要完成自己的測量過程外,

還會遍歷去調用所有子元素的measure方法,各個子元素再遞歸去執行這個流程。

1、View的measure過程

? View的measure過程由其measure方法完成,measure方法是被final修飾的方法,不能重寫。在View的measure方法中會去調用View的onMeasure方法,

因此只需要看onMeasure方法的實現即可:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }

setMeasureDimension方法會設置View的寬和高來代表測量的結束,因此我們只需要看getDefaultSize方法即可:

public static int getDefaultSize(int size, int measureSpec) {int result = size;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);switch (specMode) {case MeasureSpec.UNSPECIFIED:result = size;break;case MeasureSpec.AT_MOST:case MeasureSpec.EXACTLY:result = specSize;break;}return result; }

對于我們來說只需要看AT_MOST和EXACTLY兩種情況,其實getDefaultSize返回的大小就是measureSpec中的specSize,它就是View測量后的大小。

而UNSPECIFIED這種情況一般用于系統內部的測量過程,在這種情況下,View的大小為getDefault的第一個參數size,即寬和高分別是

getSuggestedMinimumWidth和getSuggestedMinimumHeught這兩個方法的返回值。

protected int getSuggestedMinimumHeight() {return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); } protected int getSuggestedMinimumWidth() {return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); }

可以看出,如果在沒有指定背景的情況下,寬度和高度分別是mMinWidth和mMinHeight,如果不指定該屬性,則默認為0.

如果指定背景的情況下,寬度和高度分別是max(mMinHeight, mBackground.getMinimumHeight())和max(mMinWidth, mBackground.getMinimumWidth())

那么我來看看mBackground.getMinimumWidth()方法:

public int getMinimumWidth() {final int intrinsicWidth = getIntrinsicWidth();return intrinsicWidth > 0 ? intrinsicWidth : 0; }

可以看出,在Drawable有原始寬度的情況下,該方法返回的就是Drawable的原始寬度,當然高度也是如此。

轉載于:https://www.cnblogs.com/pengjingya/p/5510714.html

總結

以上是生活随笔為你收集整理的39、自定义控件(四)-- View源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。