Android 场景Scene的使用

前言

Scene 翻译过来是场景,开发者提供起始布局和结束布局,就可以实现布局之间的过渡动画。

具体可参考 使用过渡为布局变化添加动画效果

大白话,在 Activity 的各个页面之间切换,会带有过渡动画。

打个比方,使用起来类似 Fragment ,单 Activity 多 Fragment 的情景下,为 Fragment 之间的切换添加过渡动画。

Scene 是布局之间的过渡动画,不是 Activity 之间的切换动画。

布局文件创建 Scene

主页面布局,FrameLayout 是 Scene 的父控件,以 include 的方式包含 scene1,也就是默认显示 scene1。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
    tools:context=".scene.SceneActivity">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <Button
            android:id="@+id/button_scene1"
            android:text="scene 1"
            android:onClick="onSceneButtonClick"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/button_scene2"
            android:text="scene 2"
            android:onClick="onSceneButtonClick"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/button_scene3"
            android:text="scene 3"
            android:onClick="onSceneButtonClick"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/button_scene4"
            android:text="scene 4"
            android:onClick="onSceneButtonClick"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/button_scene5"
            android:text="scene 5"
            android:onClick="onSceneButtonClick"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>

    </LinearLayout>

    <FrameLayout
        android:id="@+id/scene_root"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <include layout="@layout/scene1" />
    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

scene1 的布局,很简单,设置颜色和 Button 。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/purple_200">

    <Button
        android:text="Scene1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

其他 Scene 也类似,其他 Scene 的根布局 id 也是 android:id=“@+id/scene_container” ,就颜色和文本不同, 就不贴代码了。

初始化 Scene

通过 findViewById 找到默认的 scene1 ,

其他 Scene 用 getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context) 方法创建,

public class SceneActivity extends AppCompatActivity {

    private Scene scene1, scene2 , scene3 , scene4 , scene5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scene);
        Objects.requireNonNull(getSupportActionBar()).setTitle(SceneActivity.class.getSimpleName());

        ViewGroup mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
        scene1 = new Scene(mSceneRoot, (ViewGroup) mSceneRoot.findViewById(R.id.scene_container));

        scene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, SceneActivity.this);
        scene3 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene3, SceneActivity.this);
        scene4 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene4, SceneActivity.this);
        scene5 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene5, SceneActivity.this);

    }
}

在 Scene 之间切换

即切换不同的 Scene ,本例 5 个 button ,点击 buttonX 就切换到 SceneX 。

用默认过渡动画切换

切换用 androidx.transition.TransitionManager.go(Scene scene) 方法,切换到目标 Scene 。

这样,在 Scene 之间切换就会自带动画了,比 View.setVisibility(int visibility) 方式更丝滑、好看。

用自定义过渡动画切换

androidx.transition.TransitionManager.go(Scene scene, Transition transition) 方法,创建自定义 Transition 。

创建过渡动画 xml

创建 res/transition/ 目录,
在这里插入图片描述
选择 transition ,
在这里插入图片描述

不得不说 AS 是真的很 6 。

创建 res/transition/transition1.xml 、res/transition/transition2.xml 文件,

transition2.xml 内容

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="sequential">
    <fade android:fadingMode="fade_out" />
    <changeBounds />
    <fade android:fadingMode="fade_in" />
</transitionSet>

transition1.xml 里的内容注释掉了,为了方便看有无过度动画的差别。

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <!--<changeBounds />-->
    <!--<fade android:fadingMode="fade_in_out"/>-->
</transitionSet>

初始化Transition

初始化 Transition ,

import androidx.transition.Transition;
import androidx.transition.TransitionInflater;

private Transition transition1 , transition2 ;

transition1 = TransitionInflater.from(this).inflateTransition(R.transition.transition1);
transition2 = TransitionInflater.from(this).inflateTransition(R.transition.transition2);

切换

	public void onSceneButtonClick(View view){
        switch (view.getId()){
            case R.id.button_scene1:
                TransitionManager.go(scene1);  // 切换到 scene1
                break;
            case R.id.button_scene2: 
                TransitionManager.go(scene2); // 切换到 scene2
                break;
            case R.id.button_scene3:
                //TransitionManager.go(scene3);
                TransitionManager.go(scene3 , transition1); // 切换到 scene3 ,过渡动画用 transition1 ,transition1 为空,实际上无过渡动画
                break;
            case R.id.button_scene4:
                //TransitionManager.go(scene4);
                TransitionManager.go(scene4 , transition2); // 切换到 scene4 ,过渡动画用 transition2
                break;
            case R.id.button_scene5:
                //TransitionManager.go(scene5);
                //TransitionManager.go(scene5 , null); // 切换到 scene5 , 无过渡动画
                break;
            default:break;
        }

    }

监听场景变化

需要在 进入、退出 Scene 时做某些操作,就这样,

scene2.setEnterAction(new Runnable() {
    @Override
    public void run() {
               
    }
});

scene2.setExitAction(new Runnable() {
    @Override
    public void run() {
            
    }
});

gif对比

不加过渡动画 TransitionManager.go(sceneX , null)
在这里插入图片描述

加过渡动画 TransitionManager.go(sceneX)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Android MotionLayout 使用示例: 1. 在 XML 布局文件中添加 MotionLayout: ```xml <android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motion_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_main"> <!-- 添加子视图 --> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </android.support.constraint.motion.MotionLayout> ``` 2. 在 res/xml 目录下创建 MotionScene 文件 scene_main.xml,定义 MotionLayout 的动画场景: ```xml <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <!-- 定义起始状态 --> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:layout_marginStart="16dp" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <!-- 定义结束状态 --> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" /> </ConstraintSet> <!-- 定义转换过程 --> <Transition motion:constraintSetEnd="@id/end" motion:constraintSetStart="@id/start"> <OnSwipe motion:dragDirection="dragDown" motion:touchAnchorId="@id/text_view" motion:touchAnchorSide="top" /> </Transition> </MotionScene> ``` 3. 在 Activity 或 Fragment 中获取 MotionLayout,并启动动画: ```java MotionLayout motionLayout = findViewById(R.id.motion_layout); motionLayout.transitionToEnd(); ``` 这是一个简单的 Android MotionLayout 使用示例,你可以根据自己的需要进行更复杂的场景和动画定义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值