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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

measureChildren作品

發(fā)布時(shí)間:2025/3/13 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 measureChildren作品 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

無(wú)論是在改寫View依然是ViewGroup什么時(shí)候。特別ViewGrop什么時(shí)候,通常是不可避免的重寫onMeasure方法,我們一定會(huì)調(diào)用setMeasuredDimension()將測(cè)量好的寬高值傳遞進(jìn)去。也不免調(diào)用measureChildren方法。來(lái)測(cè)量全部的子View的大小,以下我們看看measureChildren方法是怎樣工作的。

這對(duì)我們重寫onMeasure無(wú)疑是非常有幫助的。由于一般我們都會(huì)看到這一行代碼


// 計(jì)算出全部的childView的寬和高 measureChildren(widthMeasureSpec, heightMeasureSpec);


可是它究竟測(cè)量到什么程度,滿足不滿足我們自己定義ViewGroup對(duì)以下一系列child尺寸的測(cè)量需求,不知道這個(gè)我們寫代碼就心里沒(méi)底。

所以我們有必要扒出它的老底來(lái)看看。由此來(lái)決定我們能否夠直接使用這種方法,還是因?yàn)槲覀冇泻芏嗥渌男Ч獙?shí)現(xiàn),有很多其它的因素須要考慮。這種方法不能滿足需求,須要自己寫方法來(lái)測(cè)量child。


同一時(shí)候我們?cè)谟斜匾忠淮螌懛椒▉?lái)測(cè)量child的時(shí)候,我們也要從自帶方法的思路開(kāi)始擴(kuò)展。


說(shuō)了一大堆??傊@個(gè)問(wèn)題非常重要。

以下要了解它的工作原理,我們還是要來(lái)看看源代碼:

(一)首先是measureChildren

?/**?* 遍歷全部的子view去測(cè)量自己(跳過(guò)GONE類型View)?* @param widthMeasureSpec 從父容器傳遞給子容器的布局需求(寬)* @param heightMeasureSpec 從父容器傳遞給子容器的布局需求(高)*/ ? protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { final int size = mChildrenCount; final View[] children = mChildren; for (int i = 0; i < size; ++i) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec); } } }

這部分非常easy,也就是遍歷全部的子View,假設(shè)View的狀態(tài)不是GONE就調(diào)用measureChild去進(jìn)行下一步的測(cè)量。


(二)所以我們?cè)賮?lái)看一下measureChild


/** * 測(cè)量單個(gè)視圖。將寬高和padding加在一起后交給getChildMeasureSpec去獲得終于的測(cè)量值 * @param child 須要測(cè)量的子視圖 <pre name="code" class="java">?* @param widthMeasureSpec 從父容器傳遞給子容器的布局需求(寬)* @param heightMeasureSpec 從父容器傳遞給子容器的布局需求(高) */ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { // 取得子視圖的布局參數(shù) final LayoutParams lp = child.getLayoutParams(); // 通過(guò)getChildMeasureSpec獲取終于的寬高具體測(cè)量值 final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); // 將計(jì)算好的寬高具體測(cè)量值傳入measure方法。完畢最后的測(cè)量 child.measure(childWidthMeasureSpec, childHeightMeasureSpec); }

這種方法就是對(duì)一個(gè)子視圖進(jìn)行測(cè)量。當(dāng)中一個(gè)重要的方法就是getChildMeasureSpec()。

(三)所以我們?cè)賮?lái)看一下getChildMeasureSpec

/** * * 結(jié)合父view的MeasureSpec與子view的LayoutParams信息去找到最好的結(jié)果 * (子view的確切大小由雙方面共同決定:父view的MeasureSpec 子view的LayoutParams屬性) * * @param spec 父view的MeasureSpec* @param padding view當(dāng)前尺寸的的內(nèi)邊距和外邊距(padding,margin) * @param childDimension child在當(dāng)前尺寸下的布局參數(shù)寬高值(LayoutParam.width,height) */ public static int getChildMeasureSpec(int spec, int padding, int childDimension) { //父view的模式和大小 int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); //通過(guò)父view計(jì)算出的子view = 父大小-邊距(父要求的大小。但子view不一定用這個(gè)值) int size = Math.max(0, specSize - padding); //子view想要的實(shí)際大小和模式(須要計(jì)算) int resultSize = 0; int resultMode = 0; //通過(guò)1.父view的MeasureSpec 2.子view的LayoutParams屬性這兩點(diǎn)來(lái)確定子view的大小 switch (specMode) { // 當(dāng)父view的模式為EXACITY時(shí),父view強(qiáng)加給子view確切的值 case MeasureSpec.EXACTLY: // 當(dāng)子view的LayoutParams>0也就是有確切的值 if (childDimension >= 0) { //子view大小為子自身所賦的值,模式大小為EXACTLY resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; // 當(dāng)子view的LayoutParams為MATCH_PARENT時(shí)(-1) } else if (childDimension == LayoutParams.MATCH_PARENT) { //子view大小為父view大小,模式為EXACTLY resultSize = size; resultMode = MeasureSpec.EXACTLY; // 當(dāng)子view的LayoutParams為WRAP_CONTENT時(shí)(-2) } else if (childDimension == LayoutParams.WRAP_CONTENT) { //子view決定自己的大小。但最大不能超過(guò)父view,模式為AT_MOST resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // 當(dāng)父view的模式為AT_MOST時(shí),父view強(qiáng)加給子view一個(gè)最大的值。 case MeasureSpec.AT_MOST: // 道理同上 if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) { resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // 當(dāng)父view的模式為UNSPECIFIED時(shí),子view為想要的值 case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // 子view大小為子自身所賦的值 resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // 由于父view為UNSPECIFIED,所以MATCH_PARENT的話子類大小為0 resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // 由于父view為UNSPECIFIED,所以WRAP_CONTENT的話子類大小為0 resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }

總而言之,這些推斷和設(shè)置事實(shí)上就是依據(jù)三種模式以及傳入的尺寸要求,還有須要考慮的padding和margin之后。比較全面的計(jì)算出了一個(gè)測(cè)量值,了解了這些之后我們就能夠確定什么時(shí)候須要自己寫關(guān)于子視圖的測(cè)量部分。什么時(shí)候我們僅僅須要簡(jiǎn)單的一行代碼:

// 計(jì)算出全部的childView的寬和高 measureChildren(widthMeasureSpec, heightMeasureSpec);

就能夠滿足我們的需求了,所以一切還是按需來(lái)處理。


在我個(gè)人看來(lái),這種方法考慮的比我最初想象的要全面多了,看來(lái)除了有比較特殊的需求,大部分的時(shí)候都是能夠直接使用這種方法的。這還是省了不少事的。

假設(shè)您對(duì)我提到的模式或者是重寫過(guò)程不大了解的,詳細(xì)的關(guān)于重寫onMeasure內(nèi)容請(qǐng)?jiān)斠?jiàn)我的另外一篇博客:

http://blog.csdn.net/sunmc1204953974/article/details/38454267


希望大家能有所收獲,我也是學(xué)生。有什么寫的不好的地方還請(qǐng)多多不吝賜教!

版權(quán)聲明:本文博客原創(chuàng)文章,博客,未經(jīng)同意,不得轉(zhuǎn)載。

轉(zhuǎn)載于:https://www.cnblogs.com/zfyouxi/p/4634324.html

總結(jié)

以上是生活随笔為你收集整理的measureChildren作品的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。