MaterialDesign系列文章(十二)ConstraintLayout實現的動畫效果

筆墨Android發表於2018-05-22

這幾天心情不怎麼好,加上上班的時候修改一堆的BUG,感覺整個人都不好了!但是我告訴自己不能這樣的生活,只能把所有的情緒都放在文章中吧!希望能通過寫文章讓自己變得平靜。什麼事情都會過去的!

MaterialDesign系列文章(十二)ConstraintLayout實現的動畫效果

今天我們說點什麼呢?ConstraintLayout之前在部落格中講過,當時只怪自己年少不懂事,竟不知道這東西的神奇?其實我覺得你也不知道!!!今天修改BUG百度的時候,居然看到ConstraintLayout居然能實現一些相應的動畫!感覺好神奇啊。。。為什麼我之前不知道呢!來,車不開起來,永遠不知道穩不穩!效果圖走起

這只是一個簡單的效果圖

在這裡勸大家簡單的動畫可以使用這個動畫效果,動畫複雜的話,你還是放棄吧!真心的!!!

本文知識點

  • ConstraintLayout怎麼實現動畫
  • ConstraintSet一些API的說明
  • ConstraintLayout動畫的一些案例

沒錯,今天就講這麼一點。其實我發現一件事情,每篇文章的閱讀時間不要超過10分鐘,否則你也讀不下去,我寫著也累!!!其實這個動畫效果還可以!而且實現起來還是很簡單的!主要是簡單。。。哈哈

1. ConstraintLayout怎麼實現動畫

其實我個人的理解就是通過兩個快照,然後系統替你算相應的移動,然後實現中間的過渡,所以你要做的只是實現兩個快照!快照是通過ConstraintSet實現的,切換的中間新增上動畫的設定,否則效果過於生硬!其實感覺原理就這麼多,個人感覺而已,不對的地方還請大神們指出!!!

2. ConstraintSet一些API的說明

其實動畫都是基於這個類實現的!所以這裡說一些常用的API,這樣在後面的講解也比較方便!

  • clone(ConstraintLayout constraintLayout) 克隆當前的狀態,也就相當於儲存快照!
  • applyTo(ConstraintLayout constraintLayout) 過渡到當前的快照,也就是你對constraintLayout設定了一些改變,這個方法就是過渡到設定後的效果
  • centerHorizontally(int viewId, int toView) 移動到水平中心,如果你在水平方向上有Margin可能會有偏差
  • centerVertically(int viewId, int toView) 移動到垂直中心,不過這個注意,如果你在垂直方向上有Margin可能會有偏差
  • clear(int viewId) 清除相應的控制元件
  • constrainWidth(int viewId, int width) 設定寬度
  • constrainHeight(int viewId, int height) 設定高度
  • connect(int startID, int startSide, int endID, int endSide, int margin)
    • 引數1:要新增View的ID
    • 引數2:約束條件
    • 引數3:相應的錨點
    • 引數4:相對於錨點的狀態
    • 引數5:邊距

3. ConstraintLayout動畫的一些案例

其實這個動畫,你只要記住兩個狀態就可以,一個是開始的狀態,一個是結束的狀態,中間的過渡ConstraintSet會幫你實現的!所以重點就是通過程式碼設定設定預設的狀態而已!!!所以我們從簡倒難!先實現開始佈局的那個效果!

3.1 最簡單的動畫

先實現佈局(如果對ConstraintLayout不瞭解的可以看看我之前寫的Android中佈局的優化 就能理解了!)

<?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"
    android:id="@+id/constraint"
    tools:context="com.jinlong.constraint.MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="52dp"
        android:layout_marginStart="52dp"
        android:layout_marginTop="69dp"
        android:background="@color/colorAccent"
        android:text="Button 1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="136dp"
        android:background="@color/colorPrimaryDark"
        android:text="Button 2"
        app:layout_constraintHorizontal_bias="0.571"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="88dp"
        android:layout_marginStart="88dp"
        android:layout_marginTop="102dp"
        android:background="@android:color/holo_red_dark"
        android:text="Button 3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button1" />


    <Button
        android:id="@+id/btn1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#223344"
        android:text="APPLY"
        android:onClick="applyClick"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/btn2" />

    <Button
        android:id="@+id/btn2"
        android:onClick="resetClick"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#098765"
        android:text="RESET"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@id/btn1"
        app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
複製程式碼

整個佈局檔案就是這樣子的了!這個也就是相當於最原始的狀態了!效果大概就是這樣的了!

MaterialDesign系列文章(十二)ConstraintLayout實現的動畫效果

實現動畫效果

其實別覺得程式碼多多,其實主要程式碼就幾行,最多不超過10行!

  • 建立ConstraintSet物件實現快照
    private ConstraintSet resetConstraintSet = new ConstraintSet();
    private ConstraintSet applyConstraintSet = new ConstraintSet();
複製程式碼

這兩個兩個是實現開始的快照,因為Reset的話還要變化回來的!

  • 記錄開始的快照
    applyConstraintSet.clone(mConstraintLayout);
    resetConstraintSet.clone(mConstraintLayout);
複製程式碼
  • 實現動畫
        //這個是設定相應的漸變動畫的
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
            TransitionManager.beginDelayedTransition(mConstraintLayout);
        applyConstraintSet.setMargin(R.id.button1, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button1, ConstraintSet.END, 0);
        applyConstraintSet.setMargin(R.id.button2, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button2, ConstraintSet.END, 0);
        applyConstraintSet.setMargin(R.id.button3, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button3, ConstraintSet.END, 0);
        /*
         * 設定相應居中位置的
         * 引數1:相應控制元件
         * 引數2:父控制元件
         * */
        applyConstraintSet.centerHorizontally(R.id.button1, R.id.constraint);
        applyConstraintSet.centerHorizontally(R.id.button2, R.id.constraint);
        applyConstraintSet.centerHorizontally(R.id.button3, R.id.constraint);
        applyConstraintSet.applyTo(mConstraintLayout);
複製程式碼

記得我上面說過如果你在豎直或者水平方向上有外邊距的話,居中位置會有偏差嗎?上面的程式碼就是重新設定的相應的外邊距為0,然後把三個控制元件同時居中!最後呼叫了applyTo就能實現開頭說的那個動畫了!是不是很簡單,如果你像還原的話,那麼開始建立的兩個快照就起到作用了,因為之前已經記錄的相應的快照,所以這裡直接呼叫resetConstraintSet.applyTo(mConstraintLayout);就能直接還原了!這裡有個問題,如果你不新增TransitionManager.beginDelayedTransition(mConstraintLayout);的話,位移是有的,但是十分的生硬,但是這個方法是在API19以上才生效的,所以這裡我做了相應的判斷!!!

完整程式碼

public class MainActivity extends AppCompatActivity {


    //建立兩個ConstraintSet物件(這個物件能記錄我們Constraint控制元件的所有內容)
    private ConstraintSet resetConstraintSet = new ConstraintSet();
    private ConstraintSet applyConstraintSet = new ConstraintSet();
    private ConstraintLayout mConstraintLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mConstraintLayout = findViewById(R.id.constraint);

        //克隆當前的狀態
        applyConstraintSet.clone(mConstraintLayout);
        resetConstraintSet.clone(mConstraintLayout);
    }

    public void applyClick(View view) {

        //這個是設定相應的漸變動畫的
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
            TransitionManager.beginDelayedTransition(mConstraintLayout);
        //設定居中,還有水平的居中方式哦
        applyConstraintSet.setMargin(R.id.button1, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button1, ConstraintSet.END, 0);
        applyConstraintSet.setMargin(R.id.button2, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button2, ConstraintSet.END, 0);
        applyConstraintSet.setMargin(R.id.button3, ConstraintSet.START, 0);
        applyConstraintSet.setMargin(R.id.button3, ConstraintSet.END, 0);
        /*
         * 設定相應居中位置的
         * 引數1:相應控制元件
         * 引數2:父控制元件
         * */
        applyConstraintSet.centerHorizontally(R.id.button1, R.id.constraint);
        applyConstraintSet.centerHorizontally(R.id.button2, R.id.constraint);
        applyConstraintSet.centerHorizontally(R.id.button3, R.id.constraint);
        applyConstraintSet.applyTo(mConstraintLayout);
    }

    public void resetClick(View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
            TransitionManager.beginDelayedTransition(mConstraintLayout);
        resetConstraintSet.applyTo(mConstraintLayout);
    }
}
複製程式碼

3.2 佈局檔案的實現動畫

對你沒有看錯,這裡可以載入兩個佈局檔案進行動畫效果!其實開始我覺的這個效果沒有什麼用處,但是後來感覺還是沒有什麼用處,感覺不如轉場動畫過渡的流暢!而已一個很致命的問題就是每次轉換的時候,文字都會很大的變化!感覺體驗不怎麼好!但是有些簡單的動畫感覺應該還是可以的!!!

MaterialDesign系列文章(十二)ConstraintLayout實現的動畫效果

先看下效果,如果不感興趣就可以跳過了!!!

這個感覺ConstraintLayout動畫儘量純水平的移動,或者純豎直移動,儘量不要帶有問題,否則效果不是很好!!!

上程式碼: 佈局檔案1.

<?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:src="@mipmap/icon"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/tv_des" />

    <TextView
        android:id="@+id/tv_des"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:ellipsize="end"
        android:paddingBottom="10dp"
        android:text="這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示"
        app:layout_constraintBottom_toTopOf="@id/tv_all"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@id/iv_icon"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1" />


    <TextView
        android:id="@+id/tv_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onApplyClick"
        android:text="點我顯示全部內容"
        android:textColor="#0d77e1"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="@id/iv_icon"
        app:layout_constraintLeft_toRightOf="@id/iv_icon"
        app:layout_constraintRight_toRightOf="parent" />


    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#223340"
        android:gravity="center"
        android:visibility="visible"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/iv_icon"
        app:layout_constraintVertical_weight="1" />
</android.support.constraint.ConstraintLayout>
複製程式碼

佈局檔案2

<?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"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:src="@mipmap/icon"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/tv_des" />

    <TextView
        android:id="@+id/tv_des"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:ellipsize="end"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示這是圖片的描述但是隻能顯示兩行知道嗎剩下的我都準備省略了,省略的部分我覺得會用省略號去顯示"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/iv_icon"
        app:layout_constraintVertical_weight="1" />


    <TextView
        android:id="@+id/tv_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onApplyClick"
        android:text="點我就回去了"
        android:textColor="#0d77e1"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />


    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#223340"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/iv_icon"
        app:layout_constraintVertical_weight="1" />
</android.support.constraint.ConstraintLayout>
複製程式碼

程式碼

public class Main2Activity extends AppCompatActivity {

    private ConstraintSet start = new ConstraintSet();
    private ConstraintSet end = new ConstraintSet();
    private ConstraintLayout mConstraintLayout;
    private boolean isSecond = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        mConstraintLayout = findViewById(R.id.main);
        start.clone(mConstraintLayout);
        end.clone(this, R.layout.activity_main2);

    }

    public void onApplyClick(View view) {
        if (!isSecond) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
                TransitionManager.beginDelayedTransition(mConstraintLayout);
            end.applyTo(mConstraintLayout);
            isSecond = true;
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
                TransitionManager.beginDelayedTransition(mConstraintLayout);
            start.applyTo(mConstraintLayout);
            isSecond = false;
        }
    }
}
複製程式碼

效果和上面是一樣的,但是感覺這個動畫真的很雞肋,並沒有什麼卵用!寫本片文章純屬好奇,想看看效果。看到效果之後我覺得真的沒有什麼新奇的!還不如之前的轉場動畫呢?但是做一些簡單位移動畫的話,還是比較省事的!最起碼程式碼量少了不少!好了就到這裡了!安,親們!!!

特別感謝 siegen的[譯]Constraint Layout 動畫 |動態 Constraint |用 Java 實現的 UI(這到底是什麼)[第三部分]

相關文章