Android Transition API中的场景提升

时间:2018-01-04 14:15:53

标签: android android-transitions

最近我开始使用Transition API,有一件事我无法理解。

假设我有两个场景(附上截图):

Scene A Scene B

现在,当我点击TRANSIT按钮时,我会从第1个场景转移到第2个场景,或者从第2个场景转移到第1个场景,具体取决于最后显示的场景。当我从第一个场景转移到第二个场景时,一切都按预期工作:大蓝色方块移动到屏幕的中心(通过changeBounds过渡),绿色方块从屏幕的上边缘滑入屏幕(通过slide)过渡。

当我向后转换时,会发生一些奇怪的事情:在过渡开始时,蓝色正方形被绘制在下方绿色正方形(就其高度而言)并开始移动到正如预期的那样在右上角。虽然我想要做的是将蓝色方块保持在绿色方块的顶部,并将其移动到右上角,而不改变其高度。

有什么我想念的吗?

代码的相关部分:

transition.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="together">

        <changeBounds>
            <targets>
                <target android:targetId="@id/square_view"/>
            </targets>
        </changeBounds>

        <slide android:slideEdge="top">
            <targets>
                <target android:targetId="@+id/green_square_view"/>
            </targets>
        </slide>

</transitionSet>

场景:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/green_square_view"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_marginStart="72dp"
        android:layout_marginTop="216dp"
        android:background="#0cfc28"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@id/square_view"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginBottom="180dp"
        android:background="@color/colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</android.support.constraint.ConstraintLayout>

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@id/square_view"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="@color/colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.931"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.044" />

</android.support.constraint.ConstraintLayout>

MainActivity:

package aga.android.sample.transitionssample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.transition.*
import android.util.Log
import android.view.ViewGroup
import android.widget.Button

class MainActivity : AppCompatActivity() {

    private lateinit var sceneRoot: ViewGroup

    private var currentSceneIndex = 0
    private var scenes: Array<Scene> = emptyArray()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        sceneRoot = findViewById(R.id.scene_root_view)

        scenes = arrayOf(
            Scene.getSceneForLayout(sceneRoot, R.layout.scene1, this),
            Scene.getSceneForLayout(sceneRoot, R.layout.scene2, this)
        )

        val transition = TransitionInflater.from(this).inflateTransition(R.transition.move_animation)

        findViewById<Button>(R.id.button).setOnClickListener {
            currentSceneIndex = (currentSceneIndex + 1) % 2
            TransitionManager.go(scenes[currentSceneIndex], transition)
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您发布的第二个scene.xml中不存在green_square_view。如果您也将green_square_view添加到此场景中,则绿色方块将位于蓝色方块的后面,用于两个方向。但是在这种情况下,Slide动画不再播放,因为绿色方块不会消失。对于新添加的android:visibility="invisible",可以使用green_square_view轻松修复此问题,因为幻灯片动画会对不再可用的视图以及更改“可见性”的视图做出反应。

我尝试调试导致此行为的原因。最后,我发现这可能适用part in the documentation

  

...例如,如果只是从其父级删除了View,那么View将被添加到ViewGroupOverlay中,并作为onDisappear中的view参数传递(ViewGroup,View,TransitionValues,TransitionValues)。如果可见视图更改为GONE或INVISIBLE,则可以将其用作视图,并且在动画持续时间内可见性将更改为VISIBLE。

提到的ViewGroupOverlay是在此视图组的基础上绘制的。所以这可以解释这种行为。但是我并不是100%确定这是导致问题的原因。然而,在两个场景中都有视图可以解决有问题的行为。