1.继承已有VIew,改写尺寸:重写onMeasure
SquareImageView
2.完全自定义重写onMeasure
3.自定义Layout 重写onMeasure onLayout
1.继承已有VIew,改写尺寸:重写onMeasure
流程:
重写onMeasure
用getmeasureedWidth getMeasuredHeight获取测量尺寸
计算最终尺寸
setMeasuredDissmension(w,h)保存结果
getMeasuredWidth getMeasuredHeight 测量期望尺寸,在测量过程中使用(提前取)
getWidth = right -left, geiHeight = bottom-top 实际尺寸,在非测量过程使用(更准确)
onMeasure 测量 根据自身测量和父VIew约束进行判断 ATMODE EX.....
val width = when(specMode) { MeasureSpec.EXACTLY -> specSize//精确 MeasureSpec.AT_MOST -> if ( size > specSize) specSize else size//约束,大于 else -> size //不限制 } 在kotlin 等同于下面写法,更加简洁 val width1 = resolveSize(size,widthMeasureSpec)
resolveSize 、 resolveSizeAndState 区别: 结果是一样的
还有 resolveSizeAndState 在进行自身测量和父布局给出的大小不一致时,会标记SALL,MASK,然后给父VIew一个值,父VIew会拿到结果进行重新测量
tips:很多系统ViewGroup大多数不会去读resolveSizeAndState 的TO_SMALL 等标志位
源码:
package com.example.myapplication.view import android.content.Context import android.util.AttributeSet import android.widget.ImageView import androidx.appcompat.widget.AppCompatImageView import kotlin.math.min class SquareImageView(context : Context,attributeSet: AttributeSet) : AppCompatImageView(context,attributeSet){ // override fun layout(l: Int, t: Int, r: Int, b: Int) { // // val width = r-l // val height = b-t // val size = min(width,height) // super.layout(l, t, l+size, t+size) // } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) val size = min(measuredWidth,measuredHeight) setMeasuredDimension(size,size) } }
package com.example.myapplication.view import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.util.AttributeSet import android.view.View class CircleView(context: Context,attributeSet: AttributeSet) :View(context,attributeSet) { private var paint = Paint(Paint.ANTI_ALIAS_FLAG) private val RADIUS = 300f private val PADING = 300f override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val size = ((PADING + RADIUS) * 2).toInt() val specMode = MeasureSpec.getMode(widthMeasureSpec) val specSize = MeasureSpec.getSize(widthMeasureSpec) val width = when(specMode) { MeasureSpec.EXACTLY -> specSize//精确 MeasureSpec.AT_MOST -> if ( size > specSize) specSize else size//约束,大于 else -> size //不限制 } val width1 = resolveSize(size,widthMeasureSpec) val height1 = resolveSize(size,heightMeasureSpec) setMeasuredDimension(width1,height1) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) canvas.drawCircle(PADING + RADIUS,PADING + RADIUS,RADIUS,paint) } }