本系列咱們已經介紹了ConstraintLayout的基本用法。學習到這裏,相信你已經熟悉ConstraintLayout的基本使用了,若是你對它的用法還不瞭解,建議您先閱讀我以前的文章。java
使用ConstraintLayout建立動畫的基本思想是咱們建立兩個不一樣的佈局,每一個佈局有其不一樣的約束,從而咱們使用其動畫框架來進行兩種約束之間的切換。android
以往在咱們建立簡單動畫時,一般咱們會使用app
這三種在咱們製做簡單動畫時很是簡單和方便,特別是當咱們只對某個特定的View製做動畫時。可是當咱們須要製做複雜動畫時,特別是整個頁面多個View同時執行動畫時,這幾種方式就顯得力不從心了,須要大量的工做。框架
固然還有一種方式就是使用轉場動畫框架(Transition Framework),經過共享元素(Shared Element)製做動畫,這個後面咱們也會提到。ide
咱們這裏經過一個示例來講明ConstraintLayout動畫的建立。佈局
效果:
post
代碼:學習
<?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>
咱們的初始佈局建立完畢後,咱們須要建立一個動畫結束佈局,讓動畫框架知道執行完動畫後佈局是什麼樣的。動畫
<?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>
這個頁面是咱們執行動畫結束後的樣子。那麼開始和結束的佈局咱們都有了,咱們怎樣執行動畫,讓兩個佈局之間進行過渡呢?this
答案是經過Android的TransitionManager來執行。
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);
最終效果:
只需簡單的幾行代碼,就能夠實現複雜的動畫了!固然本示例爲了說明ConstraintLayout動畫的建立方法,佈局比較簡單。
若是須要複雜佈局的動畫切換,這種方式的優點就很是明顯。若是使用傳統建立動畫方法,則有可能須要大量的時間和代碼來實現。
可能有人認爲建立兩個佈局文件不是一個好的方式,兩個佈局中存在重複的代碼,這樣好嗎?
實際上可能並無你想象的那麼很差,建立兩個佈局文件的目的只是讓動畫框架知道不一樣的約束而已,而後將不一樣的約束應用在過渡動畫中,你能夠在佈局中把與約束無關的屬性去掉。
若是你實在不喜歡建立兩個佈局文件的話,固然也能夠在代碼中來描述不一樣的約束。顯然這樣會大大增長複雜度和代碼量。
使用共享元素動畫固然也能夠實現這樣的效果,可是使用共享元素動畫你也須要建立兩個佈局,並且關鍵的不一樣是:
使用ConstraintLayout執行動畫時,動畫先後的View是同一個View對象。
而使用共享元素動畫時動畫先後的View是兩個不一樣的View對象!
本篇是本系列博客《掌握ConstraintLayout》的最後一篇。經過本系列的學習,相信你已經掌握了使用ConstraintLayout的大部分功能。
在實際開發的過程當中,使用ConstraintLayout會使開發速度有很多的提高,再結合個人另外一個系列《使用Data Binding》,會大大減小開發Android時的工做量,達到事半功倍的效果,提高生產力!
謝謝你的支持!
若有更多疑問,請參考個人其它Android相關博客:個人博客地址