不带源码的讲解都是耍流氓
package com.example.myapplication.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.TextureView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
@SuppressLint("AppCompatCustomView")
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e("TAG", "onMeasure widthMeasureSpec: "+widthMeasureSpec+" heightMeasureSpec: "+heightMeasureSpec );
Log.e("TAG", "onMeasure View.MeasureSpec.getMode(widthMeasureSpec): "+View.MeasureSpec.getMode(widthMeasureSpec) );
switch (View.MeasureSpec.getMode(widthMeasureSpec)){
case MeasureSpec.AT_MOST:
Log.e("TAG", "onMeasure AT_MOST: "+MeasureSpec.AT_MOST );
break;
case MeasureSpec.EXACTLY:
Log.e("TAG", "onMeasure EXACTLY: "+MeasureSpec.EXACTLY );
break;
case MeasureSpec.UNSPECIFIED:
Log.e("TAG", "onMeasure UNSPECIFIED: "+MeasureSpec.UNSPECIFIED );
break;
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e("TAG", "onLayout changed: "+changed+" left:"+left+" top:"+top+" right: "+right+" bottom:"+bottom );
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("TAG", "onDraw canvas: "+canvas.toString() );
}
}
运行日志显示:执行的先后顺序为onMeasure,onLayout,onDraw
1讲解onMeasure的三种模式:UNSPECIED=0<<30无限制,EXACTLY=1<<30精确地,AT_MOST=2<<30 最大是父视图
所谓的父视图就是应用到xml中的视图
<com.example.myapplication.ui.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
换句话说:
当xml中父视图是ScrollView,子视图的heightMode都是UNSPECIFIED ,无论ScrollView的高是wrap还是match;
当xml中设置为match_content或是指定大小,测量模式为:EXACTLY;
当xml中设置为wrap_content,测量模式为:AT_MOST;
UNSPECIFIED :未指定模式,也可以称为无限制模式。不受父视图的限制,比如ScrollView的childView的heightMode中
EXACTLY :精确模式。父视图指定大小,通常在 xml 中指定大小或者设为 match_parent 时会收到 EXACTLY 模式
AT_MOST :最大模式;不能超过父视图的范围,通常在 xml 中设为 wrap_content 时会收到 AT_MOST 模式。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.myapplication.ui.MyTextView
android:background="@color/cardview_shadow_start_color"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</ScrollView>
</LinearLayout>
package com.example.myapplication.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.TextureView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
@SuppressLint("AppCompatCustomView")
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e("TAG", "onMeasure widthMeasureSpec: "+widthMeasureSpec+" heightMeasureSpec: "+heightMeasureSpec );
Log.e("TAG", "onMeasure View.MeasureSpec.getMode(widthMeasureSpec): "+View.MeasureSpec.getMode(widthMeasureSpec) );
switch (View.MeasureSpec.getMode(heightMeasureSpec)){
case MeasureSpec.UNSPECIFIED:
Log.e("TAG", "onMeasure UNSPECIFIED: "+MeasureSpec.UNSPECIFIED );
break;
case MeasureSpec.EXACTLY:
Log.e("TAG", "onMeasure EXACTLY: "+MeasureSpec.EXACTLY );
break;
case MeasureSpec.AT_MOST:
Log.e("TAG", "onMeasure AT_MOST: "+MeasureSpec.AT_MOST );
break;
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e("TAG", "onLayout changed: "+changed+" left:"+left+" top:"+top+" right: "+right+" bottom:"+bottom );
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("TAG", "onDraw canvas: "+canvas.toString() );
}
}