流程

Android开发(24)——测量与布局:子控件和父容器尺寸都不

2021-04-18  本文已影响0人  让时间走12138

本节内容

1.测量单个子控件确定容器尺寸

一、测量单个子控件确定容器尺寸
1.先创建一个类,继承自ViewGroup,实现一个构造方法,并把onMeasre和onLayout方法写好。
class MyViewGroup:ViewGroup {
         constructor(context: Context, attrs: AttributeSet):super(context,attrs){}
      override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
      }
  override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
  }
}
2.在xml中把前面的类写进去,并在里面添加一个Textview
 <com.example.unknowassociation.MyViewGroup
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:background="@color/colorOrange">
       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:text="简书是一个创作社区,任何用户均可以在其上进行创作。用户在简书上面可以方便的创作自己的写作作品,互相交流。"
           android:textSize="20sp"
           android:background="@color/colorAccent"/>
   </com.example.unknowassociation.MyViewGroup>
3.在onMeasure方法里面,先定义两个变量来记录容器最终的尺寸
        var resultWidth =0
        var resultHeight = 0
4.获取子控件,并测量子控件
 val child = getChildAt(0)
 measureChild(child,widthMeasureSpec,heightMeasureSpec)
5.由于事先并不知道子控件是wrap_content,match_parent还是写死的,所以我们要先确定容器本身的尺寸和模式
        val parentWidthSize = MeasureSpec.getSize(widthMeasureSpec)
        val parentWidthMode = MeasureSpec.getMode(widthMeasureSpec)
6.先确定宽度,EXACTLY,AT_MOST还是unspecific
 when(parentWidthMode){
            MeasureSpec.EXACTLY ->  resultWidth = parentWidthSize
            MeasureSpec.AT_MOST ->  resultWidth = child.measuredWidth  +2*space
            else ->{
                resultWidth = parentWidthSize
            }
        }
7.接着确定高度,和前面一样
        val parentHeinghtSize = MeasureSpec.getSize(heightMeasureSpec)
        val parentHeightMode = MeasureSpec.getMode(heightMeasureSpec)
        when(parentHeightMode){
            MeasureSpec.EXACTLY ->  resultHeight = parentHeinghtSize
            MeasureSpec.AT_MOST ->  resultHeight = child.measuredHeight +2*space
            else ->{
                resultHeight = parentHeinghtSize
            }
        }
8.然后设置父容器尺寸
setMeasuredDimension(resultWidth,resultHeight)
9.最后在onLayout方法里面布局一下
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val child = getChildAt(0)
        var left =space
        var top= space
        var right=left+ child.measuredWidth
        var bottom=top+ child.measuredHeight
        child.layout(left,top,right,bottom)
    }
  • 为了方便修改文字,我们可以在strings.xml中添加一个属性
<string name="title">简书是一个创作社区,任何用户均可以在其上进行创作。
用户在简书上面可以方便的创作自己的写作作品,互相交流。</string>
  • 然后在.xml中把text设置为这个即可。
 android:text="@string/title"
  • 间距是很早就设置好的
 private val space = 30
最后运行一下,得到如下结果
一个控件
  • 结果发现,右边的间距好像消失了。因为我们测量的时候,使用的是measureChild方法,这个完全是依赖于父容器的,默认没有内间距。所以我们换一个方法来测量子控件。
10.通过 child.measure方法来测量子控件
        val lp = child.layoutParams
        val widthSpec = getChildMeasureSpec(widthMeasureSpec,2*space,lp.width)
        val heightSpec = getChildMeasureSpec(heightMeasureSpec,2*space,lp.height)
        child.measure(widthSpec,heightSpec)
这样右边就也会有间距了,写完之后运行程序得到如下结果。
修改之后
  • 当自己要额外去测量子控件的时候,就是用child.measure方法。一般时候都可以直接用measureChild方法。
上一篇下一篇

猜你喜欢

热点阅读