首页 > 编程知识 正文

通知栏布局下自定义宽度,表格的宽度怎么设置

时间:2023-05-06 15:50:56 阅读:143742 作者:457

需求原因适应方面,但需要有最大值或最小值限制的布局,因此需要定制View,重新打开onMeasure进行布局绘制。

我们继承了LinearLayout,准备重写onMeasure方法

classadaptivelinearlayout @ jvmoverloadsconstructor (context : context,attrs: AttributeSet?=null,defStyleAttr: Int=0,defStyleRes: Int=0) :linearlayout(context,attrs,defStyleAttr, 从efstyleres (overridefunonmeasure (widthmeasurespec : int,heightMeasureSpec: Int )//todo )中可以看出,onmeasure MeasureSpec封装了父布局传递给子布局的布局要求。 每个MeasureSpec 由 mode 和 size 组成包含父布局与子布局对应的宽度和高度要求。

MeasureSpec有三种模式:UNSPECIFIEDEXACTLYAT_MOST

UNSPECIFIED:父母的布局对子的布局没有任何限制,你觉得它有多大; 在普通自定义View中不可用; (常见于系统内部的控件,如ListView、ScrollView等。)

EXACTLY:父布局对子布局的宽度高度大小有明确要求,无论子布局想要多少,都不能超过父布局的限制; (一般指具体的大小如 100dpmatch_parent,但都是准确的大小)

AT_MOST子布局可以根据需要增大,但一般不会超过父布局的大小(通常,对应的父布局的大小为wrap_content,而父布局的子布局为子布局)

我如何得到MeasureSpec? 可以通过调用view.MeasureSpec.makemeasurespec )并将其传递给size和mode来检索measurespec。 具体来说,你可以看看源代码哦。 这里不详细说明。

valsize=100 dpvalmode=measurespec.at _ mostvalmeasurespec=view.measurespec.makemeasurespec (size, mode )的大致思路是,在调用supeer的时候,如果从母布局给出的mode为AT_MOST,则判断为再次获得最大尺寸和用AT_MOST对应的measureSpec,否则为最大尺寸和ee 然后测量。 (这样就可以做到,所以xml文件设置的是wrapcontent,就可以自适应且最大尺寸为设置的最大尺寸。如果父布局设置的是match_parent或者固定值,就直接已最大尺寸作为宽高)。 调用super.onMeasure ()后,判断测量的宽度高度是否小于设定的宽度高度,如果小于,则直接如上所述重新获取measureSpec,将宽度高度限制为最小值进行测量。 注意:此时也需要判断原来的模式是否为EXACTLY,如果是EXACTLY,则不做操作(按照不觉设置的最小值来),否则将模式设置为EXACTLY,将最小值传入,直接设置宽高为最小值测量代码如下

overridefunonmeasure (widthmeasurespec : int, heightMeasureSpec: Int )//测量最大值valwidthms=getmaxmeasurespec ) widthhhms maxWidth ) valheightms=getmaxmeasurespec (HEC ) maxHeight ) super.onmeasure ) widthms,heightMS测量最小值val minw=getminwidthmeasurespec (width ms ) val Minh=getminheightmeasuresure=minW || heightMS!=minH(super.onmeasure(minw,minh ) } } /** *得到最大值的MeasureSpec * AT_MOST子布局想要多大? 但是,一般不会超过母布

局的尺寸;(一般对应的父布局尺寸为 wrap_content,父布局无法确定子布局的尺寸)所以用来设置最大值 */ private fun getMaxMeasureSpec(measureSpec: Int, value: Int): Int { if (value > 0 && MeasureSpec.getSize(measureSpec) > value) { return if (MeasureSpec.getMode(measureSpec) == MeasureSpec.AT_MOST) { MeasureSpec.makeMeasureSpec(value, MeasureSpec.AT_MOST) } else { MeasureSpec.makeMeasureSpec(value, MeasureSpec.EXACTLY) } } return measureSpec } /** * 得到最小宽度MeasureSpec */ private fun getMinWidthMeasureSpec(measureSpec: Int): Int { return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY && measuredWidth < minWidth) { MeasureSpec.makeMeasureSpec(minWidth, MeasureSpec.EXACTLY) } else measureSpec } /** * 得到最小高度MeasureSpec */ private fun getMinHeightMeasureSpec(measureSpec: Int): Int { //父布局没有设置EXACTLY,那么此时判断测量后的高度小于最小高度,直接明确设置.如果父布局明确设置为EXACTLY 则直接设置为按照父布局的设置来 return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY && measuredHeight < minHeight) { MeasureSpec.makeMeasureSpec(minHeight, MeasureSpec.EXACTLY) } else measureSpec } 上面的测量是核心的代码思路了,下面放上完整的代码。

设置xml 属性 在attrs.xml文件中新增 所需的属性

<declare-styleable name="AdaptiveLinearLayout"> <!--最小宽度--> <attr name="min_width" format="dimension" /> <!--对打宽度--> <attr name="max_width" format="dimension" /> <!--最小高度--> <attr name="min_height" format="dimension" /> <!--最大高度--> <attr name="max_height" format="dimension" /> </declare-styleable>

AdaptiveLinearLayout的整体代码

class AdaptiveLinearLayout@JvmOverloadsconstructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) { /** * 最小宽度 */ var minWidth: Int = 0 set(value) { field = value requestLayoutAndInvalidate() } /** * 最大宽度 */ var maxWidth: Int = 0 set(value) { field = value requestLayoutAndInvalidate() } /** * 最小高度 */ var minHeight: Int = 0 set(value) { field = value requestLayoutAndInvalidate() } /** * 最大高度 */ var maxHeight: Int = 0 set(value) { field = value requestLayoutAndInvalidate() } init { //解析xml属性 val styleAttr = context.obtainStyledAttributes(attrs, R.styleable.AdaptiveLinearLayout) minWidth = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_min_width, 0F).toInt() maxWidth = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_max_width, 0F).toInt() minHeight = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_min_height, 0F).toInt() maxHeight = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_max_height, 0F).toInt() styleAttr.recycle() } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { //测量最大值 val widthMS = getMaxMeasureSpec(widthMeasureSpec, maxWidth) val heightMS = getMaxMeasureSpec(heightMeasureSpec, maxHeight) super.onMeasure(widthMS, heightMS) //测量最小值 val minW = getMinWidthMeasureSpec(widthMS) val minH = getMinHeightMeasureSpec(heightMS) if (widthMS != minW || heightMS != minH) { super.onMeasure(minW, minH) } } /** * 得到最大值的MeasureSpec * AT_MOST 子布局想要多大就可以多大,但是一般来说不会超过父布局的尺寸;(一般对应的父布局尺寸为 wrap_content,父布局无法确定子布局的尺寸)所以用来设置最大值 */ private fun getMaxMeasureSpec(measureSpec: Int, value: Int): Int { if (value > 0 && MeasureSpec.getSize(measureSpec) > value) { return if (MeasureSpec.getMode(measureSpec) == MeasureSpec.AT_MOST) { MeasureSpec.makeMeasureSpec(value, MeasureSpec.AT_MOST) } else { MeasureSpec.makeMeasureSpec(value, MeasureSpec.EXACTLY) } } return measureSpec } /** * 得到最小宽度MeasureSpec */ private fun getMinWidthMeasureSpec(measureSpec: Int): Int { return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY && measuredWidth < minWidth) { MeasureSpec.makeMeasureSpec(minWidth, MeasureSpec.EXACTLY) } else measureSpec } /** * 得到最小高度MeasureSpec */ private fun getMinHeightMeasureSpec(measureSpec: Int): Int { //父布局没有设置EXACTLY,那么此时判断测量后的高度小于最小高度,直接明确设置.如果父布局明确设置为EXACTLY 则直接设置为按照父布局的设置来 return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY && measuredHeight < minHeight) { MeasureSpec.makeMeasureSpec(minHeight, MeasureSpec.EXACTLY) } else measureSpec } /** * 布局重新请求绘制 */ private fun requestLayoutAndInvalidate() { requestLayout() invalidate() }}

在布局文件中直接使用例子

<com.widget.AdaptiveLinearLayout android:id="@+id/ll_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" app:min_height="50dp" app:min_width ="50dp"app:max_height="500dp" app:max_width ="500dp"> </com.widget.AdaptiveLinearLayout>

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。