以编程方式启动动画场景

57

我有一个运动布局,其layoutDescription是这样的:app:layoutDescription="@xml/scene"

scene.xml

<MotionScene
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        motion:constraintSetStart="@layout/view_home_card_start"
        motion:constraintSetEnd="@layout/view_home_card_end"
        motion:duration="1000">
        <OnSwipe
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="left"
            motion:dragDirection="dragLeft" />
    </Transition>

</MotionScene>

我认为 view_home_card_startview_home_card_end 的 xml 与此无关。

我如何在程序中调用这个动画?

8个回答

75

最终我正在做这件事:

((MotionLayout)findViewById(R.id.motionLayout)).transitionToEnd();
((MotionLayout)findViewById(R.id.motionLayout)).transitionToStart();

如何向转换添加约束属性? - Pemba Tamang
1
请翻译以下关于编程的内容:并且你能看一下这个问题吗 https://dev59.com/MrDma4cB1Zd3GeqPCNWO - Pemba Tamang
我该如何在MotionScene中实现反向动画? - drjansari
6
如果 MotionLayout 有多个过渡,如何选择其中一个? - merwan ezio
Java: ((MotionLayout)findViewById(R.id.motionLayout)).transitionToState(R.id.end);Kotlin binding.motionLayout.transitionToState(R.id.end)在这里,R.id.end 是我们的 constraintSetId。这就是为什么这个 id 不能重复的原因。 - Marfin. F
@merwanezio Java: ((MotionLayout)findViewById(R.id.motionLayout)).transitionToState(R.id.end);Kotlin binding.motionLayout.transitionToState(R.id.end)其中R.id.end是我们的constraintSetId。这就是为什么这个id不能重复。 - undefined

20

您也可以在xml中使用以下代码实现此操作:

motion:autoTransition="animateToEnd"

motion:autoTransition="animateToStart"

这是正确的答案。完美地运行了。感谢您的回答。 - Bilal Bangash
1
在您的MotionScene中的Transition xml标签中执行此操作,类似于<Transition app:autoTransition="animateToEnd" />注意:您可以使用app代替motion或反之。 - Nathany Attipoe

8

我们可以这样简单地做: motion_layout.transitionToEnd()

但是在 Activity 恢复时,它会启动我们的动画,速度非常快,可能会错过部分或整个动画。因此,我建议添加一些延迟。

GlobalScope.launch (Dispatchers.IO){
        delay(1000)
        withContext(Dispatchers.Main){
            motion_layout.transitionToEnd()
        }
    }

如果还没有添加协程依赖项,您需要添加协程依赖项。

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'


8
如果有人从片段(fragment)中进行此操作:
  1. Import:

    import androidx.constraintlayout.motion.widget.MotionLayout;
    
  2. Instantiate MotionLayout:

    MotionLayout motionLayout = view.findViewById(R.id.your_motion_layout);
    
  3. Transition to the end/start of motion:

    motionLayout.transitionToStart();
    

或者

    motionLayout.transitionToEnd();

1
在片段中,您可能会遇到空指针异常。我建议使用视图模型来解决这个问题。在视图模型中声明一个视图状态对象(一个密封类),并从活动中观察它,这样您就可以在那里安全地调用transitionToStart()和transitionToEnd()。而且,不要在片段中使用findViewById获取MotionLayout,因为这很容易导致空指针异常。相反,您可以从片段中更改视图模型的视图状态值。 - Reza

2

如果任何人有超过2个状态(起始和结束),那么您可以通过编程调用transitionToState()方法,该方法接收状态的ID。

例如:

binding.yourMotionLayoutId.transitionToState(R.id.yourStatusId)

2
In Latest Update of Constraint **2.0.0-beta1** Layout There are Public methods add in motion layout 
        you can get these methods with the help of motionlayout id 
    **motionLayout** 

     1. public void setProgress (float pos) 
     2. public void setTransition (int
           beginId,int endId)  
     3. public void setTransitionDuration (int
               milliseconds)  public void setTransitionListener
               (MotionLayout.TransitionListener listener)

     4. public void setState (int
               id,int screenWidth, 
                             int screenHeight)

     5. if(wantShowUi)
            {
                newUserActivityBinding.coordinatorLayout.transitionToStart();
            }
            else
            {
                newUserActivityBinding.coordinatorLayout.transitionToEnd();
            }

      <android.support.constraint.motion.MotionLayout
                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:id="@+id/motionLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layoutDescription="@xml/motion_scene_01"
                tools:showPaths="true">

            <View
                    android:id="@+id/button"
                    android:background="@color/colorAccent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:soundEffectsEnabled="false"
                    tools:layout_editor_absoluteY="361dp"
                    tools:layout_editor_absoluteX="61dp"/>


        </android.support.constraint.motion.MotionLayout>

0

我正在使用transitionToState()方法,在某些操作中在状态之间进行转换。

fun navigateToPayment() {
    binding?.motionLayoutContainer?.transitionToState(R.id.statePayment)
}

fun navigateToShipping() {
    binding?.motionLayoutContainer?.transitionToState(R.id.stateShipping)
}

同样的方法也可以用于处理Activity中的返回按键。

override fun onBackPressed() {
    binding?.motionLayoutContainer?.currentState?.let{
        when(it) {
            R.id.paymentState -> {
                //go back to shipping
                binding?.layoutSheet?.transitionToState(R.id.shippingState)
            }
            R.id.shippingState -> {
                //go back to cart
                binding?.layoutSheet?.transitionToState(R.id.cartState)
            }
            else -> {
                Toast.makeText(this, "Invalid Transition State", Toast.LENGTH_SHORT).show()
            }
        }
    } ?: run{
        //finish activity
        super.onBackPressed()
    }
}

0
如果您使用Kotlin和绑定系统,甚至不需要创建动画对象,只需这样编写:binding.root.transitionToEnd()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接