场景:
自定义一个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>
展示效果:
![](https://img.haomeiwen.com/i12648131/0d301416a17f3bf7.png)
自定义ViewGroup必须重写的两个方法分别是:onMeasure、onLayout
(1)onMeasure -- 测量
- 必须测量viewGroup本身
super.onMeasure(widthMeasureSpec, heightMeasureSpec); - 必须测量所有的子布局
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(五)
网友评论