Android自定义ViewGroup之第一次接触ViewGroup
整理总结自鸿洋的博客:http://blog.csdn.net/lmj623565791/article/details/38339817/
一、com.cctvjiatao.customviewgroup.act.MainActivity.Java
需求:我们定义一个ViewGroup,内部可以传入0到4个childView,分别依次显示在左上角,右上角,左下角,右下角
publicclassMainActivityextendsAppCompatActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //setContentView(R.layout.activity_main2); //setContentView(R.layout.activity_main3); } }
二、com.cctvjiatao.customviewgroup.view.CustomViewGroup.java
一)、ViewGroup是是什么?作用呢?
1、它相当于放置View的容器。xml布局文件中,凡是以“layout”开头的属性都是和ViewGroup(即容器)相关的,比如高度(layout_height)、宽度(layout_width)、对齐方式(layout_gravity)等;
2、它给childView计算出建议的宽、高和测量模式,决定childView的位置;
为什么是“建议的宽、高”而不是直接确定呢?因为当childView的宽、高设置为wrap_content时,只有childView自己才能计算出自己的宽和高。
二)、View的作用是什么?
1、它根据测量模式和ViewGroup给出的建议的宽、高,计算出自己的宽、高;
2、在ViewGroup为其指定的区域内绘制自己的形态;
三)、View的三种测量模式
1、EXACTLY:表示设置了精确的值,一般当childView设置其宽高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
2、AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;
3、UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。
四)、ViewGroup和LayoutParams的关系
当在LinearLayout中写childView的时候,可以写layout_gravity,layout_weight属性;
而在RelativeLayout中的childView有layout_centerInParent属性,却没有layout_gravity,layout_weight,这是为什么呢?
这是因为每个ViewGroup需要指定一个LayoutParams,用于确定支持childView支持哪些属性,比如LinearLayout指定LinearLayout.LayoutParams等
如果去看LinearLayout的源码,会发现其内部定义了LinearLayout.LayoutParams,在此类中,你可以发现weight和gravity的身影。
五)、从API角度分析ViewGroup和View的作用
View根据ViewGroup传入的测量值和测量模式,确定自己的宽、高(在onMeasure中完成),然后在onDraw中完成对自己的绘制;
ViewGroup需要给View传入View的测量值和测量模式(在onMeasure中完成),而且对于此ViewGroup的父布局,ViewGroup也要在onMeasure中完成对自己宽、高的确定;
ViewGroup需要再onLayout中完成对其childView的位置的指定。
publicclassCustomViewGroupextendsViewGroup{ publicCustomViewGroup(Contextcontext){ super(context); } publicCustomViewGroup(Contextcontext,AttributeSetattrs){ super(context,attrs); } publicCustomViewGroup(Contextcontext,AttributeSetattrs,intdefStyleAttr){ super(context,attrs,defStyleAttr); } /** *一、重写generateLayoutParams,确定该ViewGroup的LayoutParams *返回MarginLayoutParams的实例,这样就为我们的ViewGroup指定了其LayoutParams为MarginLayoutParams */ @Override publicLayoutParamsgenerateLayoutParams(AttributeSetattrs){ returnnewMarginLayoutParams(getContext(),attrs); } /** *二、计算所有ChildView的宽度和高度然后根据ChildView的计算结果,设置自己的宽和高 */ @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){ //1、获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式 intwidthMode=MeasureSpec.getMode(widthMeasureSpec); intheightMode=MeasureSpec.getMode(heightMeasureSpec); intsizeWidth=MeasureSpec.getSize(widthMeasureSpec); intsizeHeight=MeasureSpec.getSize(heightMeasureSpec); //2、计算出所有的childView的宽和高 measureChildren(widthMeasureSpec,heightMeasureSpec); //3、如果ViewGroup布局是wrap_content时,根据childView的尺寸,计算容器的宽和高 intwidth=0;//ViewGroup的宽度 intheight=0;//ViewGroup的高度 intcCount=getChildCount();//childView的数量 intcWidth=0;//childView的总宽度 intcHeight=0;//childView的总高度 MarginLayoutParamscParams=null;//View的测量模式 intlHeight=0;//用于计算左边两个childView的高度 intrHeight=0;//用于计算右边两个childView的高度,最终高度取二者之间大值 inttWidth=0;//用于计算上边两个childView的宽度 intbWidth=0;//用于计算下面两个childiew的宽度,最终宽度取二者之间大值 for(inti=0;i<cCount;i++){ ViewchildView=getChildAt(i); cWidth=childView.getMeasuredWidth(); cHeight=childView.getMeasuredHeight(); cParams=(MarginLayoutParams)childView.getLayoutParams(); if(i==0||i==1){//上面两个childView tWidth+=cWidth+cParams.leftMargin+cParams.rightMargin; } if(i==2||i==3){//下面两个childView bWidth+=cWidth+cParams.leftMargin+cParams.rightMargin; } if(i==0||i==2){//左面两个childView lHeight+=cHeight+cParams.topMargin+cParams.bottomMargin; } if(i==1||i==3){//右面两个childView rHeight+=cHeight+cParams.topMargin+cParams.bottomMargin; } } width=Math.max(tWidth,bWidth);//取最大宽度 height=Math.max(lHeight,rHeight);//去最大高度 //4、如果是wrap_content设置为我们计算的值;否则直接设置为父容器计算的值 setMeasuredDimension( (widthMode==MeasureSpec.EXACTLY)?sizeWidth:width, (heightMode==MeasureSpec.EXACTLY)?sizeHeight:height ); } /** *三、重写onLayout,对其所有childView进行定位(设置childView的绘制区域) */ @Override protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){ intcCount=getChildCount(); intcWidth=0; intcHeight=0; MarginLayoutParamscParams=null; //遍历所有childView根据其宽和高,以及margin进行布局 for(inti=0;i<cCount;i++){ ViewchildView=getChildAt(i); cWidth=childView.getMeasuredWidth(); cHeight=childView.getMeasuredHeight(); cParams=(MarginLayoutParams)childView.getLayoutParams(); intcl=0,ct=0,cr=0,cb=0; switch(i){ case0: cl=cParams.leftMargin; ct=cParams.topMargin; break; case1: cl=getWidth()-cWidth-cParams.leftMargin-cParams.rightMargin; ct=cParams.topMargin; break; case2: cl=cParams.leftMargin; ct=getHeight()-cHeight-cParams.bottomMargin; break; case3: cl=getWidth()-cWidth-cParams.leftMargin-cParams.rightMargin; ct=getHeight()-cHeight-cParams.bottomMargin; break; } cr=cl+cWidth; cb=cHeight+ct; childView.layout(cl,ct,cr,cb); } } }
三、三种布局
activity_main.xml
<com.cctvjiatao.customviewgroup.view.CustomViewGroupxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="200dp" android:layout_height="200dp" android:background="#AA333333"> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#FF4444" android:gravity="center" android:text="0" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#00ff00" android:gravity="center" android:text="1" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" android:gravity="center" android:text="2" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" android:gravity="center" android:text="3" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> </com.cctvjiatao.customviewgroup.view.CustomViewGroup>
activity_main2.xml
<com.cctvjiatao.customviewgroup.view.CustomViewGroupxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#AA333333"> <TextView android:layout_width="150dp" android:layout_height="150dp" android:background="#E5ED05" android:gravity="center" android:text="0" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#00ff00" android:gravity="center" android:text="1" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" android:gravity="center" android:text="2" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" android:gravity="center" android:text="3" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> </com.cctvjiatao.customviewgroup.view.CustomViewGroup>
activity_main3.xml
<com.cctvjiatao.customviewgroup.view.CustomViewGroupxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#AA333333"> <TextView android:layout_width="150dp" android:layout_height="150dp" android:background="#E5ED05" android:gravity="center" android:text="0" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#00ff00" android:gravity="center" android:text="1" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" android:gravity="center" android:text="2" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> <TextView android:layout_width="150dp" android:layout_height="150dp" android:background="#0000ff" android:gravity="center" android:text="3" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold"/> </com.cctvjiatao.customviewgroup.view.CustomViewGroup>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。