1. 动态控制
我个人对它的定义是:区别于使用xml的方式,使用代码来实现对View的约束控制的这么一种方式叫动态控制。虽然有的databinding
以后, xml也并不完全是“静态的”,在这里不做过多无意义的争论。其实XML是Android实现UI的常见方式,已经可以实现大部分的需求,但是恰当的加入一些动态控制也是对实现需求的一种不错补充。
2. 什么是ConstraintLayout(约束布局)
约束布局ConstraintLayout
是一个ViewGroup,可以在API 9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件,是对LinearLayout
、RelatedLayout
的一种补充或者说取代。
如何在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必须是ConstraintLayout
,connect()
函数传入的ID必须是它包含的子View的ID, 否则设置无效
网友评论