轉(zhuǎn)自:Constraint Layout 2.0 several new features-2
Constraint Layout Practice and Summary-1
Constraint Layout 2.0 several new features-2
Flow
Flow是虛擬布局(virtual layout,因此不會(huì)將級(jí)別添加到布局層次結(jié)構(gòu)中)。類似于一個(gè)鏈,可以快速的橫向或縱向布局constraint_referenced_ids里面所有的elements,通過(guò)flow_wrapMode可以指定三種展示方式。
- wrap none: 簡(jiǎn)單的創(chuàng)建一個(gè)鏈,所有引用的視圖以一條鏈的方式進(jìn)行布局,如果內(nèi)容溢出則溢出內(nèi)容不可見(jiàn)。
- wrap chain: 根據(jù)空間的大小創(chuàng)建一個(gè)或多個(gè)鏈,當(dāng)出現(xiàn)溢出時(shí),溢出的內(nèi)容會(huì)自動(dòng)換行,以新的一條鏈的方式進(jìn)行布局。
- wrap aligned: 與wrap chain相似,列的元素會(huì)對(duì)齊。
// 省略width、height、textColor等代碼
<TextView
android:id="@+id/tvZi"
android:text="子" />
// tvChou,tvYin,tvMao,tvChen,tvSi,tvWu,tvWei等代碼同tvZi一致
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="match_parent"
android:layout_height="0dp"
app:constraint_referenced_ids="tvZi,tvChou,tvYin,tvMao,tvChen,tvSi,tvWu,tvWei"
app:flow_horizontalGap="8dp"
app:flow_verticalGap="10dp"
app:flow_wrapMode="aligned" />
三種展示方式的效果(圖片來(lái)自網(wǎng)絡(luò)):

還可以配合其他屬性進(jìn)行不同需求的展示:
- flow_horizontalStyle = "spread|spread_inside|packed"
- flow_verticalStyle = "spread|spread_inside|packed"
- flow_horizontalBias = "float"
- flow_verticalBias = "float"
- flow_horizontalGap = "dimension"
- flow_verticalGap = "dimension"
- flow_horizontalAlign = "start|end"
- flow_verticalAlign = "top|bottom|center|baseline
Layer
作為一種新的輔助工具,可以讓您在多個(gè)視圖上創(chuàng)建一個(gè)虛擬的圖層。同Flow不同,它并不會(huì)對(duì)視圖進(jìn)行布局,而是對(duì)多個(gè)視圖同時(shí)進(jìn)行變換(transformation)操作,比如多個(gè)視圖整體進(jìn)行旋轉(zhuǎn)(rotate)、平移(translate)或縮放(scale)操作,Layer 將會(huì)是最佳的選擇。
// 部分代碼省略
<androidx.constraintlayout.helper.widget.Layer
android:id="@+id/layer"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/corner_white"
app:constraint_referenced_ids="tvZi,tvChou,tvYin,tvMao"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--子丑寅卯辰巳午未申酉戌亥-->
<TextView
android:id="@+id/tvZi"
android:text="子"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="50dp"
android:layout_marginTop="16dp" />
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_layer)
layerDemo()
}
/**
* 執(zhí)行l(wèi)ayer區(qū)域動(dòng)畫
*/
private fun layerDemo() {
val layer = findViewById<Layer>(R.id.layer)
val valueAnimator = ValueAnimator.ofFloat(0f, 60f, -30f, 0f, -20f, 0f, -8f, 0f)
valueAnimator.addUpdateListener(AnimatorUpdateListener { animation ->
if (null == animation.animatedValue) {
return@AnimatorUpdateListener
}
val animatedValue = animation.animatedValue.toString().toFloat()
layer.translationX = animatedValue
})
valueAnimator.duration = 800
valueAnimator.start()
}
執(zhí)行效果如下,所有控件類似snack移動(dòng)效果。

ConstraintHelper
Flow和Layer均繼承自ConstraintHelper,類屬于輔助工具類,而且可以自定義實(shí)現(xiàn)。
1、ConstraintHelper持有view的引用,所以可以獲取views(getViews)對(duì)其進(jìn)行操作,提供了·onLayout·前后的回調(diào)(updatePreLayout)。
以下是對(duì)view作出CircularReveal的效果,ViewAnimationUtils給我們提供了createCircularReveal這個(gè)函數(shù),
class CircularAnimationHelper @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
// updatePostLayout會(huì)在onLayout之后調(diào)用,在這里做動(dòng)畫
override fun updatePostLayout(container: ConstraintLayout) {
super.updatePostLayout(container)
val views = getViews(container)
views.forEach {
// 計(jì)算出中心點(diǎn)centerX,centerY和endRadius(半徑)
val createCircularReveal = ViewAnimationUtils.createCircularReveal(it, it.width / 2,
it.height / 2, 0f,
hypot((it.height / 2).toDouble(), (it.width / 2).toDouble()).toFloat()
);
createCircularReveal.duration = 1000 + Random.nextLong(500) * Random.nextInt(5)
createCircularReveal.start()
}
}
}
2、CircularRevealHelper可以直接在xml里面使用,在constraint_referenced_ids里面指定需要做動(dòng)畫view。如果有其他view也有同樣的需求則直接復(fù)用即可。
<TextView
android:id="@+id/tvZi"
android:text="子"
android:textColor="#ffffff"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="50dp"
android:layout_marginTop="16dp" />
<cn.edu.iflifeonlyasfirstseen.constraint.layout.CircularAnimationHelper
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tvZi,tvChou,tvYin,tvMao" />
<cn.edu.iflifeonlyasfirstseen.constraint.layout.FlyhereAnimationHelper
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tvMao,tvYin" />
3、執(zhí)行效果,由中心向四周擴(kuò)散和飛入效果


ImageFilterView
An ImageView that can display, combine and filter images. Added in 2.0
Subclass of ImageView to handle various common filtering operations
一個(gè)可以顯示,合并和過(guò)濾的圖像,放在utils.widget目錄中的一個(gè)View,繼承自AppCompatImageView。
屬性
| Attributes | Meaning |
|---|---|
| altSrc | 提供src圖像的替代圖像以允許淡入淡出 |
| saturation | 設(shè)置圖像的飽和度。 0 =灰度,1 =原始,2 =超飽和 |
| brightness | 設(shè)置圖像的亮度。 0 =黑色,1 =原始,2 =兩倍的亮度 |
| warmth | 調(diào)整圖像的表觀色溫。 1 =中性,2 =溫暖,.5 =冷 |
| contrast | 設(shè)置對(duì)比度。 1 =不變,0 =灰色,2 =高對(duì)比度 |
| crossfade | 設(shè)置兩個(gè)圖像之間的當(dāng)前混合。 0 = src 1 = altSrc圖片 |
| round | 用于實(shí)現(xiàn)圓角,以 dimension 為值, call the TransitionListener with this trigger id |
| roundPercent | 用于實(shí)現(xiàn)圓角,取值在0f-1f之間,為1f時(shí)將形成一張圓形圖片 |
| overlay | 定義替換圖像是在原始圖像上淡入淡出還是與其交叉淡入淡出。 默認(rèn)為true。對(duì)于半透明對(duì)象設(shè)置為false |
布局中添加ImageFilterView,
// activity_image_filter.xml
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/iv_1"
android:layout_width="120dp"
android:layout_height="120dp"
app:srcCompat="@mipmap/cat" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/iv_7"
android:layout_width="120dp"
android:layout_height="120dp"
app:altSrc="@drawable/tiger"
app:srcCompat="@drawable/cat" />
<!-- Omit code... -->
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="match_parent"
android:layout_height="0dp"
app:constraint_referenced_ids="iv_1,iv_2,iv_3,iv_4,iv_5,iv_6,iv_7,iv_8"
app:flow_horizontalGap="40dp"
app:flow_horizontalStyle="packed"
app:flow_verticalGap="20dp"
app:flow_wrapMode="aligned" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:max="100"
android:progress="0"
app:layout_constraintBottom_toBottomOf="parent" />
通過(guò)seekbar來(lái)更改屬性值演示效果。
class ImageFilterActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_image_filter)
val iv1: ImageFilterView = findViewById(R.id.iv_1)
// ...Omit code
val seekBar: SeekBar = findViewById(R.id.seekbar)
seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
// 如果是用戶行為觸發(fā)的,才作相應(yīng)操作。false為code執(zhí)行。
val realProgress = (progress / 100.0).toFloat()
iv1.saturation = realProgress * 10
iv2.brightness = 1 - realProgress
iv3.warmth = realProgress * 20
iv4.contrast = realProgress * 2
iv5.round = realProgress * 100
iv6.roundPercent = realProgress
iv7.crossfade = realProgress
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
// TODO("not yet implemented")
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
}
執(zhí)行效果

輸出是最好的輸入方式!