• 自定义ViewGroup2-已知子视图,父视图未知


    本次主要是已知子视图的大小,父视图是未知的,父视图的大小随着所包裹内容的大小而变化

    效果图如下

             

    如图所示:父视图为绿色背景,小方块即子视图为蓝色背景,父视图所包裹的内容有多大,其大小就有多大,

    子视图的多少是在layout-xml文件中改变的

    在xml文件中的调用

    <?xml version="1.0" encoding="utf-8"?>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <--自定义视图的调用-->
    <com.example.myviewgroup2.myViewGroup
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@color/colorAccent">
    <--子视图的添加,子视图的宽高均为150dp-->
    <View
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_marginStart="25dp"
    android:layout_marginTop="25dp"
    android:background="@color/colorPrimaryDark"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
    <View
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_marginStart="25dp"
    android:layout_marginTop="25dp"
    android:background="@color/colorPrimaryDark"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
    <View
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_marginStart="25dp"
    android:layout_marginTop="25dp"
    android:background="@color/colorPrimaryDark"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
     <View
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_marginStart="25dp"
    android:layout_marginTop="25dp"
    android:background="@color/colorPrimaryDark"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

    </com.example.myviewgroup2.myViewGroup>

    </androidx.constraintlayout.widget.ConstraintLayout>
    自定义ViewGroup的步骤
    1:自定义一个类继承与ViewGroup
    class myViewGroup:ViewGroup {}
    2:实现它的构造方法,这里只需要用到xml配置文件所以就只实现了xml的构造方法
    //实现xml配置文件的构造函数
    constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet){}
    3:实现必要的两个方法
    (1):
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)}
    在该方法中测量子视图的大小,以及确定父视图的大小,
    (1.1):通过循环测量子视图的大小
    //测量每一个孩子的大小
    for (i in 0 until childCount){
    val child = getChildAt(i)
    measureChild(child,widthMeasureSpec,heightMeasureSpec)
    }
    (1.2):确定父视图的大小
    //获取父容器的size与model
    val parentHeightModel = MeasureSpec.getMode(heightMeasureSpec)
    val parentWidthModel = MeasureSpec.getMode(widthMeasureSpec)
    val parentHeightSize = MeasureSpec.getSize(heightMeasureSpec)
    val parentWidthSize = MeasureSpec.getSize(widthMeasureSpec)
    确定父容器的大小
    //确定父容器的大小
    for (i in 0 until childCount){
    val child = getChildAt(i)
    val lp = child.layoutParams
    //确定容器的宽度
    if (i == 0){
    //是第一个
    //父容器的宽度为装载一个子视图的容器
    if (parentWidthModel == MeasureSpec.AT_MOST){
    //父容器被设置为wrop_content时,为AT_MOST
    //也就是父容器的大小是没有被确定的是需要自己确定的
    parentWidth = lp.width + space
    }else{
    parentWidth = parentWidthSize
    }
    }else{
    //后面的宽度一定
    //只变化高度
    if (parentWidthModel == MeasureSpec.AT_MOST){
    parentWidth = (lp.width+space)*2}else{
    parentWidth = parentWidthSize
    }
    }
    //确定高度
    if (i%2 == 0){
    //进入到下一行了
    if (parentHeightModel == MeasureSpec.AT_MOST){
    parentHeight += lp.height+space
    }else{
    parentHeight = parentHeightSize
    }
    }
    }
    将父容器的大小记录下来
    setMeasuredDimension(parentWidth,parentHeight)
       (2):
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {}
    在该方法中确切布局子视图,也就是将子视图布局到容器中的去
     var top = space
    var left = space
    var bottom = 0
    var right = 0
    for (i in 0 until childCount){
    val child = getChildAt(i)
    val lp = child.layoutParams

    bottom = top+lp.height
    right = left + lp.width
    if (i < 1){
    child.layout(left,top,right,bottom)
    left += (lp.width+space)
    }else{
    if (i%2 == 0){
    //换行了
    left = space
    top += lp.height+space
    bottom = top+lp.height
    right = left + lp.width
    child.layout(left,top,right,bottom)
    left += lp.width+space
    }else{
    child.layout(left,top,right,bottom)
    }
    }
    }
    }


    自定义viewGroup类的代码
    package com.example.myviewgroup2

    import android.content.Context
    import android.util.AttributeSet
    import android.util.Log
    import android.view.ViewGroup

    class myViewGroup:ViewGroup {
    //子视图外间距
    val space = 25
    //实现xml配置文件的构造函数
    constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet){}
    //测量子控件的大小,和确定父控件的大小
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    //保存父容器的宽高 在没有内容时只有一个间隙
    var parentHeight = space
    var parentWidth = space
    //获取父容器的size与model
    val parentHeightModel = MeasureSpec.getMode(heightMeasureSpec)
    val parentWidthModel = MeasureSpec.getMode(widthMeasureSpec)
    val parentHeightSize = MeasureSpec.getSize(heightMeasureSpec)
    val parentWidthSize = MeasureSpec.getSize(widthMeasureSpec)
    //测量每一个孩子的大小
    for (i in 0 until childCount){
    val child = getChildAt(i)
    measureChild(child,widthMeasureSpec,heightMeasureSpec)
    }
    //确定父容器的大小
    for (i in 0 until childCount){
    val child = getChildAt(i)
    val lp = child.layoutParams
    //确定容器的宽度
    if (i == 0){
    //是第一个
    //父容器的宽度为装载一个子视图的容器
    if (parentWidthModel == MeasureSpec.AT_MOST){
    //父容器被设置为wrop_content时,为AT_MOST
    //也就是父容器的大小是没有被确定的是需要自己确定的
    parentWidth = lp.width + space
    }else{
    parentWidth = parentWidthSize
    }
    }else{
    //后面的宽度一定
    //只变化高度
    if (parentWidthModel == MeasureSpec.AT_MOST){
    parentWidth = (lp.width+space)*2}else{
    parentWidth = parentWidthSize
    }
    }
    //确定高度
    if (i%2 == 0){
    //进入到下一行了
    if (parentHeightModel == MeasureSpec.AT_MOST){
    parentHeight += lp.height+space
    }else{
    parentHeight = parentHeightSize
    }
    }
    }
    //记录父容器的大小
    setMeasuredDimension(parentWidth,parentHeight)
    }
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
    var top = space
    var left = space
    var bottom = 0
    var right = 0
    for (i in 0 until childCount){
    val child = getChildAt(i)
    val lp = child.layoutParams

    bottom = top+lp.height
    right = left + lp.width
    if (i < 1){
    child.layout(left,top,right,bottom)
    left += (lp.width+space)
    }else{
    if (i%2 == 0){
    //换行了
    left = space
    top += lp.height+space
    bottom = top+lp.height
    right = left + lp.width
    child.layout(left,top,right,bottom)
    left += lp.width+space
    }else{
    child.layout(left,top,right,bottom)
    }
    }
    }
    }

    }



     
  • 相关阅读:
    数字孪生城市
    Cesium建筑自定义光源效果[转]
    实景三维电子沙盘
    三维数字沙盘+GIS = F3DGIS
    Prometheus + Grafana(八)系统监控之Kafka
    Shell 调用 py 脚本,接收返回值
    Python集合(Set)常用操作
    influxdb的retention policy
    MySQL创建用户与授权
    使用 CronJob 运行自动化任务
  • 原文地址:https://www.cnblogs.com/luofangli/p/13957939.html
Copyright © 2020-2023  润新知