attrArray.recycle(); } //此視圖是否自行繪制 setWillNotDraw(false); } /** *?負(fù)責(zé)設(shè)置子控件的測量模式和大小?根據(jù)所有子控件設(shè)置自己的寬和高 */ @Override protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{ super.onMeasure(widthMeasureSpec,?heightMeasureSpec); MLog.e(getClass().getName(),"onMeasure"); //?獲得它的父容器為它設(shè)置的測量模式和大小 int?sizeWidth?=?MeasureSpec.getSize(widthMeasureSpec); int?sizeHeight?=?MeasureSpec.getSize(heightMeasureSpec); int?modeWidth?=?MeasureSpec.getMode(widthMeasureSpec); int?modeHeight?=?MeasureSpec.getMode(heightMeasureSpec); //?如果是warp_content情況下,,記錄寬和高 int?width?=?0; int?height?=?0; //記錄每一行的寬度,,width不斷取最大寬度 int?lineWidth?=?0; //每一行的高度,,累加至height int?lineHeight?=?0; int?count?=?getChildCount(); int?left?=?getPaddingLeft(); int?top?=?getPaddingTop(); //?遍歷每個子元素 for?(int?i?=?0;?i?<?count;?i++)?{ View?child?=?getChildAt(i); if?(child.getVisibility()?==?GONE) continue; //?測量每一個child的寬和高 measureChild(child,?widthMeasureSpec,?heightMeasureSpec); //?得到child的lp ViewGroup.LayoutParams?lp?=?child.getLayoutParams(); //?當(dāng)前子空間實際占據(jù)的寬度 int?childWidth?=?child.getMeasuredWidth()?+?childHorizontalSpace; //?當(dāng)前子空間實際占據(jù)的高度 int?childHeight?=?child.getMeasuredHeight()?+?childVerticalSpace; if?(lp?!=?null?&&?lp?instanceof?MarginLayoutParams)?{ MarginLayoutParams?params?=?(MarginLayoutParams)?lp; childWidth?+=?params.leftMargin?+?params.rightMargin; childHeight?+=?params.topMargin?+?params.bottomMargin; } //如果加入當(dāng)前child,則超出最大寬度,,則的到目前最大寬度給width,,類加height?然后開啟新行 if?(lineWidth?+?childWidth?>?sizeWidth?-?getPaddingLeft()?-?getPaddingRight())?{ width?=?Math.max(lineWidth,?childWidth);//?取最大的 lineWidth?=?childWidth;?//?重新開啟新行,開始記錄 //?疊加當(dāng)前高度,, height?+=?lineHeight; //?開啟記錄下一行的高度 lineHeight?=?childHeight; child.setTag(new?Location(left,?top?+?height,?childWidth 《Android學(xué)習(xí)筆記總結(jié)+最新移動架構(gòu)視頻+大廠安卓面試真題+項目實戰(zhàn)源碼講義》 瀏覽器打開:qq.cn.hn/FTe 開源分享 ?+?left?-?childHorizontalSpace,?height?+?child.getMeasuredHeight()?+?top)); }?else?{ //?否則累加值lineWidth,lineHeight取最大高度 child.setTag(new?Location(lineWidth?+?left,?top?+?height,?lineWidth?+?childWidth?-?childHorizontalSpace?+?left,?height?+?child.getMeasuredHeight()?+?top)); lineWidth?+=?childWidth; lineHeight?=?Math.max(lineHeight,?childHeight); } } width?=?Math.max(width,?lineWidth)?+?getPaddingLeft()?+?getPaddingRight(); height?+=?lineHeight; sizeHeight?+=?getPaddingTop()?+?getPaddingBottom(); height?+=?getPaddingTop()?+?getPaddingBottom(); setMeasuredDimension((modeWidth??MeasureSpec.EXACTLY)???sizeWidth?:?width,?(modeHeight??MeasureSpec.EXACTLY)???sizeHeight?:?height); } /** *?記錄子控件的坐標(biāo) */ public?class?Location?{ public?Location(int?left,?int?top,?int?right,?int?bottom)?{ this.left?=?left; this.top?=?top; this.right?=?right; this.bottom?=?bottom; } public?int?left; public?int?top; public?int?right; public?int?bottom; } //計算當(dāng)前View以及子View的位置 @Override protected?void?onLayout(boolean?changed,?int?l,?int?t,?int?r,?int?b)?{ MLog.e(getClass().getName(),"onLayout"); //獲取子View個數(shù) int?count?=?getChildCount(); for?(int?i?=?0;?i?<?count;?i++)?{ //獲取子View View?child?=?getChildAt(i); //判斷是否顯示 if?(child.getVisibility()?==?GONE) continue; //獲取子View的坐標(biāo) Location?location?=?(Location)?child.getTag(); //設(shè)置子View位置 child.layout(location.left,?location.top,?location.right,?location.bottom); } } @Override protected?void?onSizeChanged(int?w,?int?h,?int?oldw,?int?oldh)?{ super.onSizeChanged(w,?h,?oldw,?oldh); MLog.e(getClass().getName(),"onSizeChanged"); } @Override protected?void?onDraw(Canvas?canvas)?{ super.onDraw(canvas); MLog.e(getClass().getName(),"onDraw"); } } 2.使用自定義CustomLayout<com.scc.demo.view.CustomLayout?xmlns:android="http://schemas./apk/res/android" xmlns:custom="http://schemas./apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/dimen_20" custom:horizontalSpace="10dp" custom:verticalSpace="20dp"> <TextView style="@style/TvStyle" android:text="破陣子·為陳同甫賦壯詞以寄"?/> <TextView style="@style/TvStyle" android:text="宋·辛棄疾"?/> <TextView style="@style/TvStyle" android:text="醉里挑燈看劍"?/> <TextView style="@style/TvStyle" android:text="夢回吹角連營"?/> <TextView style="@style/TvStyle" android:text="八百里分麾下炙"?/> <TextView style="@style/TvStyle" android:text="五十弦翻塞外聲"?/> <TextView style="@style/TvStyle" android:text="沙場秋點兵"?/> <TextView style="@style/TvStyle" android:text="馬作的盧飛快"?/> <TextView style="@style/TvStyle" android:text="弓如霹靂弦驚(增加點長度)"?/> <TextView style="@style/TvStyle" android:text="了卻君王天下事"?/> <TextView style="@style/TvStyle" android:text="贏得生前身后名"?/> <TextView style="@style/TvStyle" android:text="可憐白發(fā)生,!"?/> </com.scc.demo.view.CustomLayout> 3.自定義屬性在app/src/main/res/values/attrs.xml中添加屬性 <declare-styleable?name="CustomLayout"> <attr?name="verticalSpace"?format="dimension"?/> <attr?name="horizontalSpace"?format="dimension"?/> 4.使用自定義屬性
一定要添加:xmlns:test=”http://schemas./apk/res-auto”添加之后才能在xml中自定義屬性,如下代碼: <com.scc.demo.view.CustomLayout?xmlns:android="http://schemas./apk/res/android" xmlns:custom="http://schemas./apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/dimen_20" custom:horizontalSpace="10dp" custom:verticalSpace="20dp"> </com.scc.demo.view.CustomLayout>
TypedArray?attrArray?=?context.obtainStyledAttributes(attrs,?R.styleable.CustomLayout); if?(attrArray?!=?null)?{ //參數(shù)1:獲取xml中設(shè)置的參數(shù),;參數(shù)2:獲取失敗2使用參數(shù)作為默認(rèn)值 childHorizontalSpace?=?attrArray.getDimensionPixelSize(R.styleable.CustomLayout_horizontalSpace,?12); childVerticalSpace?=?attrArray.getDimensionPixelSize(R.styleable.CustomLayout_verticalSpace,?12); MLog.e(getClass().getName(),"HorizontalSpace:"+childHorizontalSpace+"|VerticalSpace:"+childVerticalSpace); //TypedArray對象池的大小默認(rèn)為5,使用時記得調(diào)用recyle()方法將不用的對象返回至對象池來達(dá)到重用的目的,。 attrArray.recycle(); } 寫到這里自定義ViewGroup基本完成,。 ViewGroup屬性 |
|
來自: 新用戶6594HGU4 > 《待分類》