ConstraintSet的简单实用和实现关键帧动画

673 阅读2分钟

ConstraintSet简介和作用

ConstraintSet是ConstraintLayout约束布局中所有组件的属性集合,只能应用于约束布局,约束布局中的组件会按照ConstraintSet中的属性重新绘制。

可以利用ConstraintSet动态设置组件的约束属性,也可以用来实现关键帧动画。

ConstraintSet的使用

创建和初始化

private val endConstraintSet by lazy { ConstraintSet() }

拷贝约束属性

可以通过clone()拷贝约束集数据,该函数遍历传入布局的子view,一一复制他们的属性:

//从布局文件中拷贝,填入Context和目标布局id,最终调用clone(ConstraintLayout constraintLayout):
public void clone(Context context, int constraintLayoutId) {...}
//从约束集中拷贝:
public void clone(ConstraintSet set) {...}
//从约束布局中拷贝:
public void clone(ConstraintLayout constraintLayout) {...}
//直接从约束中拷贝:
public void clone(Constraints constraints) {...}

加载约束属性

也可以通过load()加载约束集数据:

//resourceId为目标布局文件id
public void load(Context context, int resourceId)
public void load(Context context, XmlPullParser parser)

修改属性值

通过setXXX(int viewId,T... attr)设置约束集中单个组件的属性,根据具体函数在变长参数位置填入对应属性值。

通过源码可以看到,大部分组件的属性都是无法获取到的 ,只有少数属性width、heigh、visibility可以通过getXXX(int viewId)获取。

约束集的应用

约束集中的属性分为约束属性和非约束属性,可以选择应用哪一种属性。

  • 应用所有属性到目标布局:applyTo(ConstraintLayout constraintLayout)

  • 只应用约束属性:applyToWithoutCustom(ConstraintLayout constraintLayout)

  • 应用非约束属性:applyCustomAttributes(ConstraintLayout constraintLayout)

  • 将所有属性应用到某一个组件:applyToLayoutParams(int id, LayoutParams layoutParams),参数填入该组件的id和LayoutParams

ConstraintSet实现关键帧动画

关键帧动画根据动画的初始状态和结束状态渲染,需要分别写出初始状态和结束状态的布局文件。先将布局设置为初始状态,利用ConstraintSet复制最终状态的属性,再将这个ConstraintSet应用到布局。中间通过TransitionManager渲染动画,这样就能实现关键帧动画。

代码示例:

//创建约束集
private val endConstraintSet by lazy { ConstraintSet() }
private val startConstraintSet by lazy { ConstraintSet() }
//动画时间2000ms    
private val mTransition by lazy { AutoTransition().apply { setDuration(2000) } }

//克隆属性
private fun initAnimate() {
        startConstraintSet.clone(this, R.layout.activity_test_start)
        endConstraintSet.clone(this, R.layout.activity_test_end)
    }

private var animated = false
    private fun animatekeyFrame() {
        //constraintSet表示下一个状态的约束集
        val constraintSet = if (animated) startConstraintSet else endConstraintSet
        //渲染动画
        TransitionManager.beginDelayedTransition(viewBinding.root, mTransition)
        //将约束集应用到根布局
        constraintSet.applyTo(viewBinding.root)
        animated = !animated
    }


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_test_start)
    //点击按钮切换页面状态
    viewBinding.testBtn.setOnClickListener {
            animatekeyFrame()
        }
}    

初始状态:

1170229271c27f56e3a44374d525fb51811ce7df.png

结束状态:

49da18d123850d30c77b6a8821309124c6f4baed.png

动画过程:

b84e0c359599a5651c2b696639379c7718b7089e.gif