Android自定义View

自定义ViewGroup(一)

2018-08-06  本文已影响14人  NoBugException

场景:

自定义一个ViewGroup, 使得所有的子view垂直摆放。

学习自定义ViewGroup(一)的前提条件:
Android屏幕适配及DisplayMetrics解析
Android onMeasure、Measure、measureChild、measureChildren 的一些区别

下面开始学习自定义ViewGroup的第一课:

先展示代码:

import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

public class ViewGroupDemo1 extends ViewGroup{

    public ViewGroupDemo1(Context context) {
    super(context);
    }

    public ViewGroupDemo1(Context context, AttributeSet attrs) {
    super(context, attrs);
    }

    public ViewGroupDemo1(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ViewGroupDemo1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//重写父类的onMeasure方法
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);//测量父布局
    Log.d("ViewGroupDemo1", "==========测量===========");
    measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子布局
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bootom) {//重写父类的onLayout方法
    Log.d("ViewGroupDemo1", "==========onLayout===========");

    int height = 0;
    View child;
     //遍历所有的子布局
    for(int i=0;i<getChildCount();i++){
        //获取子布局
        child = getChildAt(i);
        //摆放
        child.layout(0, height, child.getMeasuredWidth(), height + child.getMeasuredHeight());
        //计算下一个子布局摆放的高度
        height = height + child.getMeasuredHeight();
    }
    }
}


<com.hezuo.viewgroup1.viewgroupdemo.ViewGroupDemo1
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="战三"/>
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="战三阿萨德"/>
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="战三儿童"/>
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="日太阳能"/>
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="似人非人温柔温柔"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="奥术大师大多"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="让他一人一人头"/>
</com.hezuo.viewgroup1.viewgroupdemo.ViewGroupDemo1>

展示效果:


图片.png

自定义ViewGroup必须重写的两个方法分别是:onMeasure、onLayout

(1)onMeasure -- 测量
  1. 必须测量viewGroup本身
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  2. 必须测量所有的子布局
    measureChildren(widthMeasureSpec, heightMeasureSpec);
(2)onLayout -- 布局的摆放
view.layout(左, 上, 右, 下);
遗留问题:

根据日志打印发现几个特别的现象
(1)当viewGroup布局有match_parent或者fill_parent时,执行的顺序是

onMeasure -- onMeasure -- onLayout

(2)当viewGroup布局是wrap_content或者固定数值的时候,执行顺序是

onMeasure  -- onLayout

(3)onMeasure 和onLayout总是执行了两个轮回,即:

onMeasure -- onMeasure -- onLayout -- onMeasure -- onMeasure -- onLayout

或者

onMeasure  -- onLayout -- onMeasure  -- onLayout

一个轮回为什么会执行两次onMeasure ?(1)和(2)两种情况有什么区别 ?为什么会执行两个轮回 ?

导航:

Android屏幕适配及DisplayMetrics解析
Android onMeasure、Measure、measureChild、measureChildren 的一些区别
自定义ViewGroup(一)
自定义ViewGroup(二)
自定义ViewGroup(三)
自定义ViewGroup(四)
自定义ViewGroup(五)

上一篇下一篇

猜你喜欢

热点阅读