转自: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,因此不会将级别添加到布局层次结构中)。类似于一个链,可以快速的横向或纵向布局constraint_referenced_ids
里面所有的elements
,通过flow_wrapMode
可以指定三种展示方式。
- wrap none: 简单的创建一个链,所有引用的视图以一条链的方式进行布局,如果内容溢出则溢出内容不可见。
- wrap chain: 根据空间的大小创建一个或多个链,当出现溢出时,溢出的内容会自动换行,以新的一条链的方式进行布局。
- wrap aligned: 与wrap chain相似,列的元素会对齐。
// 省略width、height、textColor等代码
// tvChou,tvYin,tvMao,tvChen,tvSi,tvWu,tvWei等代码同tvZi一致
三种展示方式的效果(图片来自网络):
还可以配合其他属性进行不同需求的展示:
- 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
作为一种新的辅助工具,可以让您在多个视图上创建一个虚拟的图层。同Flow
不同,它并不会对视图进行布局,而是对多个视图同时进行变换(transformation)操作,比如多个视图整体进行旋转(rotate)、平移(translate)或缩放(scale)操作,Layer
将会是最佳的选择。
// 部分代码省略
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_layer)
layerDemo()
}
/**
* 执行layer区域动画
*/
private fun layerDemo() {
val layer = findViewById(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()
}
执行效果如下,所有控件类似snack移动效果。
ConstraintHelper
Flow
和Layer
均继承自ConstraintHelper
,类属于辅助工具类,而且可以自定义实现。
1、ConstraintHelper
持有view
的引用,所以可以获取views
(getViews)对其进行操作,提供了·onLayout·前后的回调(updatePreLayout)。
以下是对view作出CircularReveal
的效果,ViewAnimationUtils
给我们提供了createCircularReveal
这个函数,
class CircularAnimationHelper @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
// updatePostLayout会在onLayout之后调用,在这里做动画
override fun updatePostLayout(container: ConstraintLayout) {
super.updatePostLayout(container)
val views = getViews(container)
views.forEach {
// 计算出中心点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
里面指定需要做动画view
。如果有其他view也有同样的需求则直接复用即可。
3、执行效果,由中心向四周扩散和飞入效果
ImageFilterView
An ImageView that can display, combine and filter images. Added in 2.0
Subclass of ImageView to handle various common filtering operations
一个可以显示,合并和过滤的图像,放在utils.widget
目录中的一个View
,继承自AppCompatImageView
。
属性
Attributes | Meaning |
---|---|
altSrc | 提供src图像的替代图像以允许淡入淡出 |
saturation | 设置图像的饱和度。 0 =灰度,1 =原始,2 =超饱和 |
brightness | 设置图像的亮度。 0 =黑色,1 =原始,2 =两倍的亮度 |
warmth | 调整图像的表观色温。 1 =中性,2 =温暖,.5 =冷 |
contrast | 设置对比度。 1 =不变,0 =灰色,2 =高对比度 |
crossfade | 设置两个图像之间的当前混合。 0 = src 1 = altSrc图片 |
round | 用于实现圆角,以 dimension 为值, call the TransitionListener with this trigger id |
roundPercent | 用于实现圆角,取值在0f-1f 之间,为1f 时将形成一张圆形图片 |
overlay | 定义替换图像是在原始图像上淡入淡出还是与其交叉淡入淡出。 默认为true。对于半透明对象设置为false |
布局中添加ImageFilterView
,
// activity_image_filter.xml
通过seekbar来更改属性值演示效果。
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) {
// 如果是用户行为触发的,才作相应操作。false为code执行。
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?) {
}
})
}
执行效果
输出是最好的输入方式!