美文网首页Android
ConstraintLayout代码动态控制约束布局

ConstraintLayout代码动态控制约束布局

作者: 寻水的鱼Chock | 来源:发表于2021-11-26 16:20 被阅读0次

    1. 动态控制

    我个人对它的定义是:区别于使用xml的方式,使用代码来实现对View的约束控制的这么一种方式叫动态控制。虽然有的databinding以后, xml也并不完全是“静态的”,在这里不做过多无意义的争论。其实XML是Android实现UI的常见方式,已经可以实现大部分的需求,但是恰当的加入一些动态控制也是对实现需求的一种不错补充。

    2. 什么是ConstraintLayout(约束布局)

    约束布局ConstraintLayout是一个ViewGroup,可以在API 9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件,是对LinearLayoutRelatedLayout的一种补充或者说取代。
    如何在XML中使用ConstraintLayout在此也不做过多的说明,网上已有很多资料,请君移步查阅。

    3. ConstraintLayout初体验

    val mWebView = findViewById<WebView>(R.id.mWebView)
    if (mWebView.layoutParams is ConstraintLayout.LayoutParams) {
        val pView = mWebView.parent
        if (pView is ConstraintLayout) {
            val bottomView = LayoutInflater.from(this)
                .inflate(R.layout.item_entry_web_bottom_view, pView, false)
            bottomView.id = View.generateViewId()
            pView.addView(bottomView)
            val cs = ConstraintSet()
            cs.clone(pView)
            cs.clear(mWebView.id)
            val pId = ConstraintLayout.LayoutParams.PARENT_ID
            cs.connect(mWebView.id, ConstraintSet.TOP, pId, ConstraintSet.TOP)
            cs.connect(mWebView.id, ConstraintSet.START, pId, ConstraintSet.START)
            cs.connect(mWebView.id, ConstraintSet.END, pId, ConstraintSet.END)
            cs.connect(mWebView.id, ConstraintSet.BOTTOM, bottomView.id, ConstraintSet.TOP)
            cs.applyTo(pView)
        }
    }
    

    这是一段在布局底部插入一个自定义xml布局的代码片段。
    原始xml的定义

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <WebView
            android:id="@+id/mWebView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    增加代码后的等效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"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <WebView
            android:id="@+id/mWebView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/botton_view"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <include
            android:id="@+id/botton_view"
            layout="@layout/item_entry_web_bottom_view" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    3. 什么情况下使用

    能修改XML达到需求时尽量使用XML定义的方式进行UI修改,便于后续代码的维护。那什么情况下不得不使用代码控制呢?
    1、原本代码已有封装,但未提供可实现需求的扩展,且没有源码无法修改XML定义时。
    2、需要使用代码控制的其他情况。

    4. 常见的布局约束等效举例

    还是以以上举例中的XML为例进行说明

    4.1 新建布局约束
    val cs = ConstraintSet()
    
    4.2 从已有的XML约束中克隆
    cs.clone(pView)
    

    克隆有很多好处,可以省去很多原本已有的约束代码。

    4.3 清除特定View已有的XML约束
    cs.clear(mWebView.id)
    

    配合克隆使用最佳。

    4.4 XML等效代码举例
    app:layout_constraintTop_toTopOf="parent"
    =>
    val pId = ConstraintLayout.LayoutParams.PARENT_ID
    cs.connect(mWebView.id, ConstraintSet.TOP, pId, ConstraintSet.TOP)
    
    app:layout_constraintTop_toTopOf="@+id/botton_view"
    =>
    cs.connect(mWebView.id, ConstraintSet.TOP, bottonView.id, ConstraintSet.TOP)
    

    举一反三,相应的

    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    

    也都好理解了, 相应的

    cs.connect(mWebView.id, ConstraintSet.START, pId, ConstraintSet.START)
    cs.connect(mWebView.id, ConstraintSet.TOP, pId, ConstraintSet.TOP)
    cs.connect(mWebView.id, ConstraintSet.END, pId, ConstraintSet.END)
    cs.connect(mWebView.id, ConstraintSet.BOTTOM, pId, ConstraintSet.BOTTOM)
    

    只需要更换第二和第四个参数, 就可以实现layout_constraint###_to###Of的所有随机组合。
    第一个参数就是你写layout_constraint###_to###Of所在的那个View ID
    第三个参数就是layout_constraint###_to###Of等于后面的那个View ID
    是不是很简单?是的。但是~
    最后别忘了

    cs.applyTo(pView)
    

    其中需要特别注意的是: pView必须是ConstraintLayoutconnect()函数传入的ID必须是它包含的子View的ID, 否则设置无效

    相关文章

      网友评论

        本文标题:ConstraintLayout代码动态控制约束布局

        本文链接:https://www.haomeiwen.com/subject/zxqxxrtx.html