保存到桌面加入收藏设为首页
IOS开发
当前位置:首页 > IOS开发

【自定义控件】自定义ViewGroup在ViewGroup中显示TextView-安度博客

时间:2019-02-04 14:57:50   作者:   来源:   阅读:76   评论:0
内容摘要:需求:在ViewGroup中显示一个TextView1、继承ViewGroup必须要实现其构造方法和一个onLayout方法构造函数的处理:public CusViewGroup(Context context) { this(context null);}public CusV......
  • 需求:在ViewGroup中显示一个TextView

    1、继承ViewGroup

    必须要实现其构造方法和一个onLayout方法

    构造函数的处理

    public CusViewGroup(Context context) { this(context null);}public CusViewGroup(Context context AttributeSet attrs) { this(context attrs 0);}public CusViewGroup(Context context AttributeSet attrs int defStyleAttr) { super(context attrs defStyleAttr); }

    注意构造函数中的this。自定义ViewGroup也能够有自己的属性,对于属性的操作和自定义View一致。(在Style中添加自定义属性,在构造函数中获取到layout中设置的自定义属性的值)

    onLayout():
    疑问:为什么必须要重写onLayout方法?
    自定义ViewGroup 相当于是一个容器,里面能够放置很多View,这些View的位置由onLayout来确定。必须指定位置,才能显示到容器的对应位置上。

    疑问:onLayout的几个参数是什么意思
    l、t、r、b 是自定义ViewGroup父控件中设置的Padding 值。

    2、自定义ViewGroup的执行过程

    构造函数—–获取自定义属性
    onMeasure—控件宽、高以及measure子控件
    onLayout —–控件的位置,子View的位置
    onDraw —— 画画咯

    onMeasure
    自定义ViewGroup onMeasure代码

    /** * 确定ViewGroup的宽高 * * @param widthMeasureSpec 宽参数 * @param heightMeasureSpec 高参数 */@Overrideprotected void onMeasure(int widthMeasureSpec int heightMeasureSpec) { //ViewGroup主要是一个容器,当ViewGroup的宽高是确切的值的时候,控件的宽高就是它本身设置的值 //主要是考虑ViewGroup Wrap_content的时,需要计算控件的宽高,控件的宽高根据子View的布局来计算 int width; int height; int mWidthMeasureMode = MeasureSpec.getMode(widthMeasureSpec); measureChildren(widthMeasureSpec heightMeasureSpec);//初始化所有子View的宽高 if (mWidthMeasureMode == MeasureSpec.AT_MOST) {//Wrap_content的情况 //测量子View的宽 怎么测量子View的宽 //由于这里只有一个控件,暂时从这个一个控件开始学习 View childView = getChildAt(0);//获取到这个控件 width = childView.getMeasuredWidth(); } else { width = MeasureSpec.getSize(widthMeasureSpec); } int mHeightMeasureMode = MeasureSpec.getMode(heightMeasureSpec); if (mHeightMeasureMode == MeasureSpec.AT_MOST) { View childView = getChildAt(0); height = childView.getMeasuredHeight(); } else { height = MeasureSpec.getSize(heightMeasureSpec); } setMeasuredDimension(width height);}

    测试布局文件:

    <com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup android:layout_width=&#39;wrap_content&#39; android:layout_height=&#39;100dp&#39; android:background=&#39;#ccc&#39;> <TextView android:layout_width=&#39;100dp&#39; android:layout_height=&#39;50dp&#39; android:background=&#39;#FF4444&#39; android:gravity=&#39;center&#39; android:text=&#39;0&#39; android:textColor=&#39;#FFFFFF&#39; android:textStyle=&#39;bold&#39; /></com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup>

    这里只设置了自定义ViewGroup 的宽度wrap_content
    效果

    这里写图片描述

    宽度此时就为TextView的宽度 高度还是自定义控件的高度
    这个时候,你发现TextView根本没有显示到界面上,进入下一步

    onLayout
    疑问:onLayout():控件摆放到什么位置?
    —onLayout的几个参数是父控件的padding值

    疑问:是否能够改变padding值?
    —不能,子控件怎么能够设置父控件的属性呢!!

    疑问:怎么将TextView显示到界面上?

    /** * 必须实现的方法,自定义ViewGroup的child位置布局 * * @param changed * @param l ViewGroup父类 paddingLeft * @param t paddingTop * @param r paddingRight * @param b paddingBottom */@Overrideprotected void onLayout(boolean changed int l int t int r int b) { Log.e(TAG&#39;paddingLeft=&#39;+l+&#39;;paddingTop=&#39;+t+&#39;;paddingRight=&#39;+r+&#39;;paddingBottom=&#39;+b); //是否能对自定义ViewGroup再进行位置的变换?不能!!!!! //将TextView显示出来 View childView = getChildAt(0); childView.layout(00childView.getMeasuredWidth()childView.getMeasuredHeight());}

    显示结果:

    这里写图片描述

    到此就基本完成了ViewGroup的简单示例

    Demo下载
    http://download.csdn.net/detail/u012391876/9677845


    练习:在ViewGroup中显示2个TextView 并实现指定布局

    效果图:

    这里写图片描述

    自定义ViewGroup代码:

    ViewGroup:package com.tjstudy.cusviewgroupdemo.customerview;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;/** * 自定义ViewGroup 按效果显示两个TextView */public class CusViewGroup extends ViewGroup { public static final String TAG = &#39;CusViewGroup&#39;; private int childCount; public CusViewGroup(Context context) { this(context null); } public CusViewGroup(Context context AttributeSet attrs) { this(context attrs 0); } public CusViewGroup(Context context AttributeSet attrs int defStyleAttr) { super(context attrs defStyleAttr); } /** * 必须实现的方法,自定义ViewGroup的child位置布局 * * @param changed * @param l ViewGroup父类 paddingLeft * @param t paddingTop * @param r paddingRight * @param b paddingBottom */ @Override protected void onLayout(boolean changed int l int t int r int b) { int cl = 0; int ct = 0; int cr = 0; int cb = 0; int h = 0;//由于两个控件垂直放置,需要记录高度 //为每一个子View指定位置 所需效果:查看mipmap里面的效果图 for(int i=0;i<childCount;i++){ View childView = getChildAt(i); if(i==0){//第一个放到上面的中间 cl = (getMeasuredWidth()-childView.getMeasuredWidth())/2; ct = 0; cr = cl+childView.getMeasuredWidth(); cb = ct+childView.getMeasuredHeight(); h = ct+childView.getMeasuredHeight(); } if(i==1){ cl=0; ct=h; cr=cl+childView.getMeasuredWidth(); cb=cb+childView.getMeasuredHeight(); } childView.layout(clctcrcb); } } /** * 确定ViewGroup的宽高 * * @param widthMeasureSpec 宽参数 * @param heightMeasureSpec 高参数 */ @Override protected void onMeasure(int widthMeasureSpec int heightMeasureSpec) { //ViewGroup主要是一个容器,当ViewGroup的宽高是确切的值的时候,控件的宽高就是它本身设置的值 //主要是考虑ViewGroup Wrap_content的时候,此时就需要计算控件的宽高了,控件的宽高就是子View的总的宽高 int width = 0; int height = 0; int mWidthMeasureMode = MeasureSpec.getMode(widthMeasureSpec); measureChildren(widthMeasureSpec heightMeasureSpec);//初始化所有子View的宽高 childCount = getChildCount(); if (mWidthMeasureMode == MeasureSpec.AT_MOST) {//Wrap_content的情况 //测量子View的宽 怎么测量子View的宽 //由于是垂直放置 这里需要最大的那个宽度 int maxWidth = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); width = childView.getMeasuredWidth(); maxWidth = (width>maxWidth)?width:maxWidth; } width = maxWidth; } else { width = MeasureSpec.getSize(widthMeasureSpec); } int mHeightMeasureMode = MeasureSpec.getMode(heightMeasureSpec); if (mHeightMeasureMode == MeasureSpec.AT_MOST) { for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); height += childView.getMeasuredHeight(); } } else { height = MeasureSpec.getSize(heightMeasureSpec); } setMeasuredDimension(width height); }}

    layout:

    <?xml version=&#39;1.0&#39; encoding=&#39;utf-8&#39;?><LinearLayout xmlns:android=&#39;http://schemas.android.com/apk/res/android&#39; xmlns:tools=&#39;http://schemas.android.com/tools&#39; android:layout_width=&#39;match_parent&#39; android:layout_height=&#39;match_parent&#39; android:orientation=&#39;vertical&#39; android:paddingBottom=&#39;@dimen/activity_vertical_margin&#39; android:paddingLeft=&#39;@dimen/activity_horizontal_margin&#39; android:paddingRight=&#39;@dimen/activity_horizontal_margin&#39; android:paddingTop=&#39;@dimen/activity_vertical_margin&#39; tools:context=&#39;com.tjstudy.cusviewgroupdemo.MainActivity&#39;> <com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup android:layout_width=&#39;wrap_content&#39; android:layout_height=&#39;wrap_content&#39; android:background=&#39;#ccc&#39;> <TextView android:layout_width=&#39;50dp&#39; android:layout_height=&#39;50dp&#39; android:background=&#39;#ED1C24&#39; android:gravity=&#39;center&#39; android:text=&#39;0&#39; android:textColor=&#39;#FFFFFF&#39; android:textStyle=&#39;bold&#39; /> <TextView android:layout_width=&#39;100dp&#39; android:layout_height=&#39;50dp&#39; android:background=&#39;#00A2E8&#39; android:gravity=&#39;center&#39; android:text=&#39;1&#39; android:textColor=&#39;#FFFFFF&#39; android:textStyle=&#39;bold&#39; /> </com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup></LinearLayout>

    运行结果:

    这里写图片描述

    疑问:对于自定义ViewGroup ,应该还会有margin、padding等的设置,这些设置是否会对ViewGroup或者子控件的位置有影响?
    原代码+打印信息打印结果:

    这里写图片描述

    设置margin+padding

    android:padding=&#39;10dp&#39;android:layout_margin=&#39;60dp&#39;

    打印信息:

    这里写图片描述

    效果图:

    这里写图片描述

    效果有变化,但是在自定义ViewGroup中打印的log信息确是相同的

    理解:在自定义ViewGroup中,onLayout中默认情况下已经计算了padding的值,margin是自定义控件本身到自定义控件父控件的位置,不会对子View有影响。

    Demo下载
    http://download.csdn.net/detail/u012391876/9677964


本站所有站内信息仅供娱乐参考,不作任何商业用途,不以营利为目的,专注分享快乐,欢迎收藏本站!
所有信息均来自:百度一下 (威尼斯人官网)