Android ConstraintLayout幻灯片过渡动画正在显示视图';s动画结束前的完整高度

Android ConstraintLayout幻灯片过渡动画正在显示视图';s动画结束前的完整高度,android,android-constraintlayout,android-transitions,constraintset,Android,Android Constraintlayout,Android Transitions,Constraintset,我有以下活动和布局: 导入android.os.Bundle 导入android.view.Gravity 导入android.view.view 导入androidx.appcompat.app.appcompat活动 导入androidx.constraintlayout.widget.constraintlayout 导入androidx.constraintlayout.widget.ConstraintSet 导入androidx.transition.Slide 导入androidx

我有以下活动和布局:

导入android.os.Bundle
导入android.view.Gravity
导入android.view.view
导入androidx.appcompat.app.appcompat活动
导入androidx.constraintlayout.widget.constraintlayout
导入androidx.constraintlayout.widget.ConstraintSet
导入androidx.transition.Slide
导入androidx.transition.TransitionManager
导入com.tests.playdy.R
类ConstraintLayoutTransitionActivity:AppCompatActivity(){
private val rootView:ConstraintLayout by lazy{findViewById(R.id.root)}
private val bottomBlueView:lazy{findViewById(R.id.bottomBlue)}查看
private val switchButton:通过惰性{findViewById(R.id.switchButton)}查看
私有变量isBottomBlueViewShowing=true
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity\u constraint\u layout\u transition)
switchButton.setOnClickListener(::onSwitchButtonClicked)
}
@同步的
单击开关按钮上的私人乐趣(视图:视图){
isBottomBlueViewShowing=!isBottomBlueViewShowing
val constraintSet=constraintSet()
constraintSet.clone(rootView)
val transition=Slide()
过渡时间=1000L
如果(IsBottomBlueView显示){
constraintSet.setVisibility(bottomBlueView.id,View.VISIBLE)
transition.slidedge=Gravity.BOTTOM
}否则{
constraintSet.setVisibility(bottomBlueView.id,View.GONE)
transition.slidedge=Gravity.BOTTOM
}
TransitionManager.beginDelayedTransition(根视图,转换)
constraintSet.applyTo(rootView)
}
}

如你所见

  • 当我隐藏视图时,按钮会直接向下移动而不设置动画(bottomBlueView动画正常)
  • 当我显示视图时,按钮也会在没有动画的情况下直接向上移动。但最让我头疼的是,在动画开始之前会显示一个白色区域,并一直保持到动画结束
有没有办法解决这些问题?
我已经尝试了很多方法(使用
ConstraintSet
Animation
),但没有一种能像预期的那样起作用。

您可以使用
自动转换
进行转换

TransitionManager.beginDelayedTransition(rootView, AutoTransition())
    
结果如下:

自动转换
使用转换来更改蓝色区域的可见性。 如果幻灯片需要蓝色区域,则应提供自定义过渡。红色区域和蓝色按钮的过渡应为
ChangeBounds
transition,蓝色区域的过渡应为
slide
transition:

private val topRed: View by lazy { findViewById(R.id.topRed) }
  
private fun onSwitchButtonClicked(view: View) {
        isBottomBlueViewShowing = !isBottomBlueViewShowing

        val transitionSet = TransitionSet()
        transitionSet.ordering = TransitionSet.ORDERING_TOGETHER

        //blue btn
        val blueBtnTransition = Slide(Gravity.BOTTOM)
        blueBtnTransition.addTarget(bottomBlueView)

        //red area + switch btn
        val topRedTransition = ChangeBounds()
        topRedTransition.addTarget(topRed)
        topRedTransition.addTarget(switchButton)

        transitionSet.addTransition(blueBtnTransition)
        transitionSet.addTransition(topRedTransition)

        val blueBtnVisibility = if (isBottomBlueViewShowing) {
            View.VISIBLE
        } else {
            View.GONE
        }

        val constraintSet = ConstraintSet()
        constraintSet.clone(rootView)
        constraintSet.setVisibility(bottomBlueView.id, blueBtnVisibility)

        TransitionManager.beginDelayedTransition(rootView, transitionSet)
        constraintSet.applyTo(rootView)
    }
结果如下:

如您所见,在设置动画时,红色和蓝色区域之间仍然存在白色区域。您可以通过向过渡添加延迟来解决此问题:

    blueBtnTransition.startDelay = if (isBottomBlueViewShowing) 0 else 100
    topRedTransition.startDelay = if (isBottomBlueViewShowing) 100 else 0
以下是结果。虽然有延迟,但看起来要好得多:


非常感谢您的详细解释。我刚刚在模拟器和物理设备上尝试过,但得到的结果与第二个gif一样。您还记得您做了什么吗?再次感谢^准确地说,没有视觉上的白色间隙。但这里的问题是,
Slide
transition使用
AccelerateInterpolator
/
DecreateInterpolator
来隐藏/显示动画,正如我从源代码中看到的那样,您不能通过
setInterpolator
方法来改变这种行为。这里最好的解决方案是编写自定义的
幻灯片
转换,该转换将支持
线性插值器
或尝试通过延迟、不同动画持续时间等来隐藏该间隙