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.viewimport android.content.Context
import android.util.AttributeSet
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatImageView
import kotlin.math.minclass 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.viewimport android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.Viewclass CircleView(context: Context,attributeSet: AttributeSet) :View(context,attributeSet) {private var paint = Paint(Paint.ANTI_ALIAS_FLAG)private val RADIUS = 300fprivate val PADING = 300foverride 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)}
}