zoukankan      html  css  js  c++  java
  • Android开发

    介绍

    本系列我们已经介绍了ConstraintLayout的基本用法。学习到这里,相信你已经熟悉ConstraintLayout的基本使用了,如果你对它的用法还不了解,建议您先阅读我之前的文章

    使用ConstraintLayout创建动画的基本思想是我们创建两个不同的布局,每个布局有其不同的约束,从而我们使用其动画框架来进行两种约束之间的切换。

    传统动画

    以往在我们创建简单动画时,通常我们会使用

    • 视图动画(View Animation)
    • 帧动画(Drawable Animation)
    • 属性动画(Property Animation)

    这三种在我们制作简单动画时非常简单和方便,特别是当我们只对某个特定的View制作动画时。但是当我们需要制作复杂动画时,特别是整个页面多个View同时执行动画时,这几种方式就显得力不从心了,需要大量的工作。

    当然还有一种方式就是使用转场动画框架(Transition Framework),通过共享元素(Shared Element)制作动画,这个后面我们也会提到。

    ConstraintLayout动画

    我们这里通过一个示例来说明ConstraintLayout动画的创建。

    1. 首先,我们创建第一个布局(activity_main.xml),它是是我们的初始布局。
    • 效果:
      -w290

    • 代码:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        android:id="@+id/cl_root"
        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=".MainActivity">
    
        <TextView
            android:id="@+id/tv_score"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="评分:8.3分"
            app:layout_constraintStart_toStartOf="@+id/tv_name"
            app:layout_constraintTop_toBottomOf="@+id/tv_name" />
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="8dp"
            android:text="无敌破坏王2"
            android:textColor="#282828"
            android:textSize="20sp"
            app:layout_constraintStart_toEndOf="@+id/iv_poster"
            app:layout_constraintTop_toTopOf="@+id/iv_poster" />
    
        <ImageView
            android:id="@+id/iv_poster"
            android:layout_width="120dp"
            android:layout_height="160dp"
            android:layout_marginStart="20dp"
            android:layout_marginTop="20dp"
            android:scaleType="centerCrop"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/wreck_it_ralph" />
    
    </android.support.constraint.ConstraintLayout>
    

    我们的初始布局创建完毕后,我们需要创建一个动画结束布局,让动画框架知道执行完动画后布局是什么样的。

    1. 创建动画结束布局(activity_main_detail.xml)。
    • 效果:

    -w289

    • 代码:
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        android:id="@+id/cl_root"
        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=".MainActivity">
    
        <TextView
            android:id="@+id/tv_score"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="52dp"
            android:text="评分:8.3分"
            app:layout_constraintBottom_toBottomOf="@+id/tv_name"
            app:layout_constraintStart_toEndOf="@+id/tv_name"
            app:layout_constraintTop_toTopOf="@+id/tv_name"/>
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="20dp"
            android:text="无敌破坏王2"
            android:textColor="#282828"
            android:textSize="20sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <ImageView
            android:id="@+id/iv_poster"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginTop="65dp"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/wreck_it_ralph" />
    
    </android.support.constraint.ConstraintLayout>
    

    这个页面是我们执行动画结束后的样子。那么开始和结束的布局我们都有了,我们怎样执行动画,让两个布局之间进行过渡呢?

    答案是通过Android的TransitionManager来执行。

    1. 使用TransitionManager来执行动画
    • 代码(MainActivity.java)
    package cn.examplecode.constraintlayoutdemo;
    
    import android.support.constraint.ConstraintLayout;
    import android.support.constraint.ConstraintSet;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.transition.TransitionManager;
    
    public class MainActivity extends AppCompatActivity {
    
        private ConstraintLayout mConstraintLayout;
        private boolean mIsDetail;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mConstraintLayout = findViewById(R.id.cl_root);
    
            ConstraintSet constraintSet1 = new ConstraintSet();
            ConstraintSet constraintSet2 = new ConstraintSet();
    
            constraintSet2.clone(this, R.layout.activity_main_detail);
            constraintSet1.clone(mConstraintLayout);
    
            findViewById(R.id.iv_poster).setOnClickListener(v -> {
                TransitionManager.beginDelayedTransition(mConstraintLayout);
                if (!mIsDetail) {
                    constraintSet2.applyTo(mConstraintLayout);
                    mIsDetail = true;
                } else {
                    constraintSet1.applyTo(mConstraintLayout);
                    mIsDetail = false;
                }
            });
        }
    }
    

    我们来解释以上代码。
    首先我们发现使用了这个类ConstraintSet,它是一个约束集合,保存了布局上所有元素的约束,因为我们需要在两个布局之间执行动画,所以我们需要创建两个约束集合的对象。

    ConstraintSet constraintSet1 = new ConstraintSet();
    ConstraintSet constraintSet2 = new ConstraintSet();
    

    创建完约束集对象后,我们需要设置每个约束集对应的约束:

    constraintSet2.clone(this, R.layout.activity_main_detail);
    constraintSet1.clone(mConstraintLayout);
    

    这里我们将当前布局的约束应用到constraintSet1中,将目标布局的约束应用到constraintSet2中。

    接下来我们执行动画:

    TransitionManager.beginDelayedTransition(mConstraintLayout);
    # 从constraintSet1过渡到constraintSet2
    constraintSet2.applyTo(mConstraintLayout);
    
    # 从constraintSet2过渡到constraintSet1
    constraintSet1.applyTo(mConstraintLayout);
    

    最终效果:

    ezgif-5-34173ef48cf2

    只需简单的几行代码,就可以实现复杂的动画了!当然本示例为了说明ConstraintLayout动画的创建方法,布局比较简单。
    如果需要复杂布局的动画切换,这种方式的优势就非常明显。如果使用传统创建动画方法,则有可能需要大量的时间和代码来实现。

    问题探讨

    为什么需要创建两个布局文件?

    可能有人认为创建两个布局文件不是一个好的方式,两个布局中存在重复的代码,这样好吗?

    实际上可能并没有你想象的那么不好,创建两个布局文件的目的只是让动画框架知道不同的约束而已,然后将不同的约束应用在过渡动画中,你可以在布局中把与约束无关的属性去掉。
    如果你实在不喜欢创建两个布局文件的话,当然也可以在代码中来描述不同的约束。显然这样会大大增加复杂度和代码量。

    与使用共享元素动画(Shared Element)有什么区别?

    使用共享元素动画当然也可以实现这样的效果,但是使用共享元素动画你也需要创建两个布局,而且关键的不同是:
    使用ConstraintLayout执行动画时,动画前后的View是同一个View对象。
    而使用共享元素动画时动画前后的View是两个不同的View对象!

    系列总结

    本篇是本系列博客《掌握ConstraintLayout》的最后一篇。通过本系列的学习,相信你已经掌握了使用ConstraintLayout的大部分功能。

    在实际开发的过程中,使用ConstraintLayout会使开发速度有不少的提升,再结合我的另一个系列《使用Data Binding》,会大大减少开发Android时的工作量,达到事半功倍的效果,提升生产力!

    谢谢你的支持!

    如有更多疑问,请参考我的其它Android相关博客:我的博客地址

  • 相关阅读:
    子网掩码的作用与IP网段的划分
    DHCP服务器
    Anaconda安装、更新第三方包
    time模块的使用
    TensorFlow安装
    机器学习-线性回归
    机器学习
    Pyhton-类(2)
    python-类(1)
    Python-函数
  • 原文地址:https://www.cnblogs.com/lloyd-zh/p/10069354.html
Copyright © 2011-2022 走看看