【自定义控件】自定义ViewGroup 在ViewGroup中显示TextView

需求:在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 高参数
 */
@Override
protected 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="wrap_content"
    android:layout_height="100dp"
    android:background="#ccc">

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#FF4444"
        android:gravity="center"
        android:text="0"
        android:textColor="#FFFFFF"
        android:textStyle="bold" />

</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
 */
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    Log.e(TAG,"paddingLeft="+l+";paddingTop="+t+";paddingRight="+r+";paddingBottom="+b);
    //是否能对自定义ViewGroup再进行位置的变换?不能!!!!!
    //将TextView显示出来
    View childView = getChildAt(0);
    childView.layout(0,0,childView.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 = "CusViewGroup";
    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(cl,ct,cr,cb);
        }
    }

    /**
     * 确定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="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.tjstudy.cusviewgroupdemo.MainActivity">

    <com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#ccc">

        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#ED1C24"
            android:gravity="center"
            android:text="0"
            android:textColor="#FFFFFF"
            android:textStyle="bold" />
        <TextView
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#00A2E8"
            android:gravity="center"
            android:text="1"
            android:textColor="#FFFFFF"
            android:textStyle="bold" />

    </com.tjstudy.cusviewgroupdemo.customerview.CusViewGroup>

</LinearLayout>

运行结果:

疑问:对于自定义ViewGroup ,应该还会有margin、padding等的设置,这些设置是否会对ViewGroup或者子控件的位置有影响?

原代码+打印信息打印结果:

设置margin+padding

android:padding="10dp"
android:layout_margin="60dp"

打印信息:

效果图:

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

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

Demo下载

http://download.csdn.net/detail/u012391876/9677964

时间: 2024-11-06 23:36:31

【自定义控件】自定义ViewGroup 在ViewGroup中显示TextView的相关文章

Android 在界面中显示以及输入文本信息 TextView和EditText

Android控件之TextView和EditTextTextView:显示文本框控件EditText:输入文本框TextView和EditText的常用属性TextView控件的常用属性android:id 控件的idandroid:layout_width 控件的宽度android:layout_height 控件的高度android:text 文本内容android:textSize 文本大小android:textColor 文本颜色android:background 控件背景Edit

Android UI编程(View、ViewGroup类、按钮、TextView、EditText)

1.View和ViewGroup类 Android中所有的UI元素都是使用View和ViewGroup类的对象建立的. View:将一些信息绘制在屏幕上可以与用户产生交互 Viewgroup:包含多个View和Viewgroup的容器,用来定义UI布局 2.按钮 (1)方式一: 配置: <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height=

我的Android进阶之旅------&gt; Android为TextView组件中显示的文本添加背景色

通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article/details/46916963) 我们学会了在TextView中显示图片的方法,现在我们来学习如何为TextView组件中显示的文本添加背景色.要求完成的样子如图所示: 首先来学习使用BackgroundColorSpan对象设置文字背景色,代码如下: TextView textView=(TextV

自定义圆形滚动条(在自定义标题栏中显示)--利用开源项目ProgressWheel(二)

本篇是ProgressWheel使用的第二篇(尾篇),功能是在自定义标题栏中显示ProgressWheel滚动条. 本篇引用的开源项目依然是ProgressWheel,地址: https://github.com/Todd-Davies/ProgressWheel 本篇效果图: 自定义滚动条(在自定义标题栏中显示)的实现: 1)activity_progress_wheel_test. xml: <RelativeLayout xmlns:android="http://schemas.a

onInterceptTouchEvent 与 onTouchEvent 分析与MotionEvent在ViewGroup与View中的分发

onInterceptTouchEvent 与 onTouchEvent 分析与MotionEvent在ViewGroup与View中的分发 Notice:本文将紧接着 Android 触屏事件 OnTouch onClick onTouchEvent对于触屏事件的处理和分发 这一片博文来分析,假设您还没有读过这一片博文,强烈建议你先读一次上述博文 OK,言归正传,我们開始吧 近期,一直听到有人在争论关于dispatchTouchEvent这个函数 和 onInterceptTouchEvent

我的Android进阶之旅------&gt; Android在TextView中显示图片方法

面试题:请说出Android SDK支持哪些方式显示富文本信息(不同颜色.大小.并包含图像的文本信息),并简要说明实现方法. 答案:Android SDK支持如下显示富文本信息的方式. 1.使用TextView组件可以显示富文本信息.在TextView组件中可以使用富文本标签来显示富文本信息,这种标签类似于HTML标签,但比HTML标签简单,支持有限的几种显示富文本的方式.如<font>标签用于设置字体和颜色,<b>用于设置粗体.包含这些标签的文本不能直接作为TextView.se

如何在XAF中显示自定义窗体和控件

https://www.devexpress.com/Support/Center/Example/Details/E911 如何在XAF中显示自定义窗体和控件,布布扣,bubuko.com

通过自定义单元格渲染器在Jtable中显示超链接

转载:http://www.tuicool.com/articles/qE7FNv 在JTable中自定义单元格渲染器是非常简单和容易的.对于单元格渲染器来说,它的主要任务就是为目标单元格返回一个Component对象,以呈现其内容.说到Component,就应该豁然开朗了,因为在Swing中,所有可在屏幕上显示的图形控件都是Component的直接或间接子类,也就是说,理论上你可以在JTable单元格中显示任意图形控件! 当然,实际上有一些控件是不能在单元格中显示的,比如JFrame这样的独立

TextView中显示带图片的html

TextView中显示带图片的html 在TextView中显示图片,HTML,实现图文混排. 下载地址:http://www.devstore.cn/code/info/626.html 运行截图: