测量宽高一般有三种模式
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec)); } private fun measureSize(size: Int): Int { var result = 0; //结果 val specMode = MeasureSpec.getMode(size); val specSize = MeasureSpec.getSize(size); when (specMode) { MeasureSpec.AT_MOST -> { // 子容器可以是声明大小内的任意大小 Log.e("lgh", "AT_MOST 子容器可以是声明大小内的任意大小") Log.e("lgh", "大小为:" + specSize) result = specSize } MeasureSpec.EXACTLY -> {//父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间. 比如EditTextView中的DrawLeft Log.e("lgh", " EXACTLY 父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间") Log.e("lgh", "大小为:" + specSize) result = specSize } MeasureSpec.UNSPECIFIED -> {//父容器对于子容器没有任何限制,子容器想要多大就多大. 所以完全取决于子view的大小 Log.e("lgh", "UNSPECIFIED 父容器对于子容器没有任何限制,子容器想要多大就多大") Log.e("lgh", "大小为:" + specSize) result = 1500; } } return result; }
一般来说,可以简化成两种情况, EXACTLY 一种,UNSPECIFIED和AT_MOST 一种,我理解是,精确值是一种,不精确时自己赋值一种
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取传入的宽高的模式 val widthMode = MeasureSpec.getMode(widthMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) //获取宽度和高度的最大尺寸 val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) //判断模式 获取最终显示的尺寸 var size: Int = 400 if (widthMode == MeasureSpec.EXACTLY) { //设置为200dp 或者match parent 都是EXACTLY if (heightMode == MeasureSpec.EXACTLY) { size = min(widthSize, heightSize) //宽高都为精确值,取最小值 } else { //宽度是精确值,高度是 wrap content size = widthSize } } else { //当设置为 wrap content 时 if (heightMode == MeasureSpec.EXACTLY) { //高度是精确值 size = heightSize } else {//宽高都是 wrap content size = 400 } } //将测量好的值设置给控件 setMeasuredDimension(size, size) }