Android開(kāi)發(fā) - 掌握ConstraintLayout(十一)復(fù)雜動(dòng)畫(huà)!如此簡(jiǎn)單署拟!

介紹

本系列我們已經(jīng)介紹了ConstraintLayout的基本用法婉宰。學(xué)習(xí)到這里,相信你已經(jīng)熟悉ConstraintLayout的基本使用了推穷,如果你對(duì)它的用法還不了解心包,建議您先閱讀我之前的文章

使用ConstraintLayout創(chuàng)建動(dòng)畫(huà)的基本思想是我們創(chuàng)建兩個(gè)不同的布局缨恒,每個(gè)布局有其不同的約束,從而我們使用其動(dòng)畫(huà)框架來(lái)進(jìn)行兩種約束之間的切換轮听。

傳統(tǒng)動(dòng)畫(huà)

以往在我們創(chuàng)建簡(jiǎn)單動(dòng)畫(huà)時(shí)骗露,通常我們會(huì)使用

  • 視圖動(dòng)畫(huà)(View Animation)
  • 幀動(dòng)畫(huà)(Drawable Animation)
  • 屬性動(dòng)畫(huà)(Property Animation)

這三種在我們制作簡(jiǎn)單動(dòng)畫(huà)時(shí)非常簡(jiǎn)單和方便,特別是當(dāng)我們只對(duì)某個(gè)特定的View制作動(dòng)畫(huà)時(shí)血巍。但是當(dāng)我們需要制作復(fù)雜動(dòng)畫(huà)時(shí)萧锉,特別是整個(gè)頁(yè)面多個(gè)View同時(shí)執(zhí)行動(dòng)畫(huà)時(shí),這幾種方式就顯得力不從心了述寡,需要大量的工作柿隙。

當(dāng)然還有一種方式就是使用轉(zhuǎn)場(chǎng)動(dòng)畫(huà)框架(Transition Framework),通過(guò)共享元素(Shared Element)制作動(dòng)畫(huà)鲫凶,這個(gè)后面我們也會(huì)提到禀崖。

ConstraintLayout動(dòng)畫(huà)

我們這里通過(guò)一個(gè)示例來(lái)說(shuō)明ConstraintLayout動(dòng)畫(huà)的創(chuàng)建。

  1. 首先螟炫,我們創(chuàng)建第一個(gè)布局(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="評(píng)分: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="無(wú)敵破壞王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>

我們的初始布局創(chuàng)建完畢后昼钻,我們需要?jiǎng)?chuàng)建一個(gè)動(dòng)畫(huà)結(jié)束布局掸屡,讓動(dòng)畫(huà)框架知道執(zhí)行完動(dòng)畫(huà)后布局是什么樣的。

  1. 創(chuàng)建動(dòng)畫(huà)結(jié)束布局(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="評(píng)分: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="無(wú)敵破壞王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>

這個(gè)頁(yè)面是我們執(zhí)行動(dòng)畫(huà)結(jié)束后的樣子仅财。那么開(kāi)始和結(jié)束的布局我們都有了,我們?cè)鯓訄?zhí)行動(dòng)畫(huà)碗淌,讓兩個(gè)布局之間進(jìn)行過(guò)渡呢盏求?

答案是通過(guò)Android的TransitionManager來(lái)執(zhí)行抖锥。

  1. 使用TransitionManager來(lái)執(zhí)行動(dòng)畫(huà)
  • 代碼(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;
            }
        });
    }
}

我們來(lái)解釋以上代碼。
首先我們發(fā)現(xiàn)使用了這個(gè)類(lèi)ConstraintSet风喇,它是一個(gè)約束集合宁改,保存了布局上所有元素的約束,因?yàn)槲覀冃枰趦蓚€(gè)布局之間執(zhí)行動(dòng)畫(huà)魂莫,所以我們需要?jiǎng)?chuàng)建兩個(gè)約束集合的對(duì)象还蹲。

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

創(chuàng)建完約束集對(duì)象后,我們需要設(shè)置每個(gè)約束集對(duì)應(yīng)的約束:

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

這里我們將當(dāng)前布局的約束應(yīng)用到constraintSet1中耙考,將目標(biāo)布局的約束應(yīng)用到constraintSet2中谜喊。

接下來(lái)我們執(zhí)行動(dòng)畫(huà):

TransitionManager.beginDelayedTransition(mConstraintLayout);
# 從constraintSet1過(guò)渡到constraintSet2
constraintSet2.applyTo(mConstraintLayout);

# 從constraintSet2過(guò)渡到constraintSet1
constraintSet1.applyTo(mConstraintLayout);

最終效果:

ezgif-5-34173ef48cf2

只需簡(jiǎn)單的幾行代碼,就可以實(shí)現(xiàn)復(fù)雜的動(dòng)畫(huà)了倦始!當(dāng)然本示例為了說(shuō)明ConstraintLayout動(dòng)畫(huà)的創(chuàng)建方法斗遏,布局比較簡(jiǎn)單。
如果需要復(fù)雜布局的動(dòng)畫(huà)切換鞋邑,這種方式的優(yōu)勢(shì)就非常明顯诵次。如果使用傳統(tǒng)創(chuàng)建動(dòng)畫(huà)方法,則有可能需要大量的時(shí)間和代碼來(lái)實(shí)現(xiàn)枚碗。

問(wèn)題探討

為什么需要?jiǎng)?chuàng)建兩個(gè)布局文件逾一?

可能有人認(rèn)為創(chuàng)建兩個(gè)布局文件不是一個(gè)好的方式,兩個(gè)布局中存在重復(fù)的代碼肮雨,這樣好嗎遵堵?

實(shí)際上可能并沒(méi)有你想象的那么不好,創(chuàng)建兩個(gè)布局文件的目的只是讓動(dòng)畫(huà)框架知道不同的約束而已怨规,然后將不同的約束應(yīng)用在過(guò)渡動(dòng)畫(huà)中陌宿,你可以在布局中把與約束無(wú)關(guān)的屬性去掉。
如果你實(shí)在不喜歡創(chuàng)建兩個(gè)布局文件的話(huà)波丰,當(dāng)然也可以在代碼中來(lái)描述不同的約束壳坪。顯然這樣會(huì)大大增加復(fù)雜度和代碼量。

與使用共享元素動(dòng)畫(huà)(Shared Element)有什么區(qū)別掰烟?

使用共享元素動(dòng)畫(huà)當(dāng)然也可以實(shí)現(xiàn)這樣的效果弥虐,但是使用共享元素動(dòng)畫(huà)你也需要?jiǎng)?chuàng)建兩個(gè)布局,而且關(guān)鍵的不同是:
使用ConstraintLayout執(zhí)行動(dòng)畫(huà)時(shí)媚赖,動(dòng)畫(huà)前后的View是同一個(gè)View對(duì)象霜瘪。
而使用共享元素動(dòng)畫(huà)時(shí)動(dòng)畫(huà)前后的View是兩個(gè)不同的View對(duì)象!

系列總結(jié)

本篇是本系列博客《掌握ConstraintLayout》的最后一篇惧磺。通過(guò)本系列的學(xué)習(xí)颖对,相信你已經(jīng)掌握了使用ConstraintLayout的大部分功能。

在實(shí)際開(kāi)發(fā)的過(guò)程中磨隘,使用ConstraintLayout會(huì)使開(kāi)發(fā)速度有不少的提升缤底,再結(jié)合我的另一個(gè)系列《使用Data Binding》顾患,會(huì)大大減少開(kāi)發(fā)Android時(shí)的工作量,達(dá)到事半功倍的效果个唧,提升生產(chǎn)力江解!

謝謝你的支持!

如有更多疑問(wèn)徙歼,請(qǐng)參考我的其它Android相關(guān)博客:我的博客地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末犁河,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子魄梯,更是在濱河造成了極大的恐慌桨螺,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酿秸,死亡現(xiàn)場(chǎng)離奇詭異灭翔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辣苏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)肝箱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人稀蟋,你說(shuō)我怎么就攤上這事煌张。” “怎么了糊治?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵唱矛,是天一觀的道長(zhǎng)罚舱。 經(jīng)常有香客問(wèn)我井辜,道長(zhǎng),這世上最難降的妖魔是什么管闷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任粥脚,我火速辦了婚禮,結(jié)果婚禮上包个,老公的妹妹穿的比我還像新娘刷允。我一直安慰自己,他們只是感情好碧囊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布树灶。 她就那樣靜靜地躺著,像睡著了一般糯而。 火紅的嫁衣襯著肌膚如雪天通。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天熄驼,我揣著相機(jī)與錄音像寒,去河邊找鬼烘豹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诺祸,可吹牛的內(nèi)容都是我干的携悯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼筷笨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼憔鬼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起奥秆,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逊彭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后构订,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體侮叮,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年悼瘾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了囊榜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亥宿,死狀恐怖卸勺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烫扼,我是刑警寧澤曙求,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站映企,受9級(jí)特大地震影響悟狱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堰氓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一挤渐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧双絮,春花似錦浴麻、人聲如沸迂猴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)强法。三九已至焚挠,卻和暖如春膏萧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工向抢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留认境,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓挟鸠,卻偏偏與公主長(zhǎng)得像叉信,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艘希,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 用兩張圖告訴你硼身,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,693評(píng)論 2 59
  • 1覆享、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_x閱讀 15,968評(píng)論 3 119
  • 測(cè)試報(bào)告核心要素 報(bào)告/工作匯報(bào) 簡(jiǎn)單記錄了下老徐的分享內(nèi)容佳遂。僅做記錄。 如何匯報(bào)撒顿?怎么匯報(bào)丑罪? 測(cè)試報(bào)告(要素):...
    鴻雁小確幸閱讀 1,623評(píng)論 0 0
  • 2018年3月,孩子學(xué)校中考前百日誓師活動(dòng)凤壁,需要家長(zhǎng)給孩子寫(xiě)一封信吩屹。在工作會(huì)議的間隙,在筆記本上寫(xiě)下了如下文字拧抖。 ...
    Anyi安逸閱讀 577評(píng)論 4 6
  • 在老鎮(zhèn)的豆瓣電臺(tái)項(xiàng)目中,用到了三個(gè)第三方庫(kù),分別是"Alamofire","SwiftyJSON","HRToas...
    Dominic1992閱讀 540評(píng)論 0 0