提筆之際(附總體思路)
最近跟幾個(gè)小伙伴在實(shí)踐一個(gè)項(xiàng)目,考慮到界面效果,我們決定使用揭露動(dòng)畫作為Activity的轉(zhuǎn)場(chǎng)動(dòng)畫。

這里主要是我負(fù)責(zé)這部分的實(shí)現(xiàn)。
話說之前是沒接觸過的,關(guān)于具體的實(shí)現(xiàn)跟大體的思路都不太清楚。于是最先啃官方API,有點(diǎn)難看懂,然后下載了官方的demo,直接看代碼,還是有問題,畢竟它規(guī)模略大,集成了好多動(dòng)畫效果;
接著就找了很多博文,發(fā)現(xiàn)網(wǎng)上真的水文忒多了哎。。
最后找到了這三篇,算是解答了我的疑問:
http://www.itdecent.cn/p/b75548e488df
這篇思路很好,寫得也很走心,啟發(fā)了我設(shè)計(jì)的思路跟注意到的一些問題,像揭露動(dòng)畫的邏輯放在哪里之類的;正當(dāng)我要下載demo的時(shí)候發(fā)現(xiàn)他代碼是kotlin來的,好吧,再繼續(xù)找博文;https://blog.csdn.net/shedoor/article/details/81251849#5
這篇就講得更加詳盡,這還看不懂那就有點(diǎn)說不過去了。一開始覺得揭露動(dòng)畫還是挺高大上的樣子,結(jié)果此博文文首便說很簡(jiǎn)單,那就很簡(jiǎn)單吧,后來理解透了之后發(fā)覺確實(shí)也不難,畢竟只有一個(gè)靜態(tài)方法而已;
https://github.com/OCNYang/Android-Animation-Set/tree/master/reveal-animation
這個(gè)點(diǎn)進(jìn)去是他的GitHub,demo下下來,代碼看一下,自己寫個(gè)小demo(我是先在一個(gè)activity里面跑通揭露動(dòng)畫,再進(jìn)一步將揭露動(dòng)畫實(shí)現(xiàn)成跳轉(zhuǎn)動(dòng)畫),再加入自己的邏輯,一步一步來算是沒有問題了。
到這里就跑通了一個(gè)活動(dòng)中的Activity了;
-
https://github.com/whyalwaysmea/AndroidDemos
接下來就進(jìn)入本文主題了,使用揭露動(dòng)畫作為Activity的轉(zhuǎn)場(chǎng)動(dòng)畫;
這篇文檔跟代碼算是幫上大忙了,有較大的參考價(jià)值;
不同的是作者的思路是在跳轉(zhuǎn)的目標(biāo)活動(dòng)中,啟動(dòng)做揭露動(dòng)畫的收挽,收挽結(jié)束后再finish();
我這里根據(jù)情況修改為跳轉(zhuǎn)的目標(biāo)活動(dòng)中按下返回鍵即finish(),完了之后原始活動(dòng)中的onReStart()中做揭露動(dòng)畫的收挽;另外我在在跳轉(zhuǎn)的目標(biāo)活動(dòng)中完成揭露動(dòng)畫展開的時(shí)候,添加了一個(gè)AlphaAnimation;
這邊的起始活動(dòng)用的是button的onClick觸發(fā)的方式,以及這里對(duì)兩個(gè)活動(dòng)各自的控件的visible做了細(xì)節(jié)的把控;


引子
使用揭露動(dòng)畫做一個(gè)絲滑的Activity轉(zhuǎn)場(chǎng)動(dòng)畫,
關(guān)于這個(gè)需求,可能不同的同學(xué),會(huì)有不同的問題,
我這里把可能遇到的問題跟我在完成這個(gè)demo的過程中遇到的問題做一個(gè)總結(jié),
然后附上總體的思路,大家可以交流一下~
什么是揭露動(dòng)畫?
Material-Animations; 官網(wǎng)有詳細(xì)的介紹,
揭露動(dòng)畫具有相當(dāng)絲滑的效果,
常常可以用與基于一個(gè)Activity的碎片切換或者View、控件的切換覆蓋鋪張,如本文第一個(gè)demo;
或者直接作為兩個(gè)Activity之間的轉(zhuǎn)場(chǎng)動(dòng)畫,如本文第二個(gè)demo;揭露動(dòng)畫怎么用?
官方API封裝好了,
一個(gè)類一個(gè)靜態(tài)方法——ViewAnimationUtils.createCircularReveal(),
傳進(jìn)五個(gè)參數(shù),返回一個(gè)Animator對(duì)象。根據(jù)具體情況調(diào)用即可。
詳細(xì)可見參考文檔;“絲滑”之解
這個(gè)轉(zhuǎn)場(chǎng)動(dòng)畫要實(shí)現(xiàn)得絲滑,需要注意幾個(gè)細(xì)節(jié):
活動(dòng)A跳轉(zhuǎn)到活動(dòng)B的情況下,
a.在A點(diǎn)擊觸發(fā)跳轉(zhuǎn)時(shí)刻,揭露動(dòng)畫要放在哪個(gè)活動(dòng)展開;
b.在B按下返回鍵之后,揭露動(dòng)畫又要放在哪個(gè)活動(dòng)收挽;
c.揭露動(dòng)畫的展開和收挽,createCircularReveal()分別以誰為操作對(duì)象;
d.這里A通過FloatingActionButton出發(fā),那揭露層View跟FloatingActionButton的visible跟invisible設(shè)置的順序;
e.關(guān)閉android默認(rèn)的activity轉(zhuǎn)場(chǎng)動(dòng)畫(不然就相當(dāng)不絲滑了hhh);相關(guān)解答詳解下方第二個(gè)demo的思路總結(jié),請(qǐng)移步到正文中的第二個(gè)demo;
了解本文的兩個(gè)demo之后,我相信以這個(gè)兩個(gè)demo為模板,結(jié)合筆者之前關(guān)于Material Design做的諸多筆記,應(yīng)該是可以做出不少很有趣的東西來的~
再附上在做本demo的過程中一些debugExperience:
正文
1.先在一個(gè)activity里面跑通揭露動(dòng)畫
首先新建一個(gè)空項(xiàng)目,接著走三步即可:
1)更改styles.xml,改成NoActionBar,去掉標(biāo)題欄,待會(huì)兒調(diào)試可以觀察:

2)書寫activity_main.xml:
- 這里對(duì)子空間的布局范圍要求并不多,直接簡(jiǎn)單用FrameLayout即可;
- 然后是Textview放在最前面,最先渲染,以為至底層;
- 接著我們這里使用一個(gè)View原生控件來作為揭露動(dòng)畫的操作對(duì)象,即通過對(duì)View控件的顯示和隱藏以及動(dòng)畫操作來具體實(shí)現(xiàn)揭露動(dòng)畫;
- 最后放置一個(gè)懸浮按鈕,用于啟動(dòng)點(diǎn)擊事件,這里響應(yīng)的事件是啟動(dòng)揭露動(dòng)畫:
另外說一下,關(guān)于FloatingActionButton,
android:backgroundTint可以設(shè)置其背景色,
android:src則給按鈕設(shè)置圖標(biāo),
這里用的圖標(biāo)資源來自于阿里的矢量圖標(biāo)庫。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="com.lwp.justtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view_puppet"
android:background="@color/colorPrimaryDark"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:backgroundTint="@color/colorPrimary"
android:src="@drawable/map"
app:pressedTranslationZ="10dp" />
</FrameLayout>
3)書寫MainActivity.java:
- 實(shí)例化各個(gè)組件之后,實(shí)現(xiàn)FloatingActionButton的onClick(),
- onClick()中我們調(diào)用一個(gè)自定義方法,在里面啟動(dòng)揭露動(dòng)畫;
- 這里通過變量flag實(shí)現(xiàn)點(diǎn)擊按鈕時(shí)揭露動(dòng)畫的交替開啟顯示以及關(guān)閉隱藏,效果圖在下方代碼之后;
- 關(guān)于揭露動(dòng)畫的邏輯以及具體實(shí)現(xiàn)的語法,
其實(shí)核心就是ViewAnimationUtils.createCircularReveal()這個(gè)方法以及其五個(gè)參數(shù)的意義,
詳細(xì)地可以參考前面提到的參考文章鏈接:
package com.lwp.justtest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
boolean flag = false;
FloatingActionButton fab;
private View mPuppet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPuppet = findViewById(R.id.view_puppet);
fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(this);
}
@Override
public void onClick(View v) {
doRevealAnimation();
}
private void doRevealAnimation() {
int[] vLocation = new int[2];
fab.getLocationInWindow(vLocation);
int centerX = vLocation[0] + fab.getMeasuredWidth() / 2;
int centerY = vLocation[1] + fab.getMeasuredHeight() / 2;
int height = mPuppet.getHeight();
int width = mPuppet.getWidth();
int maxRradius = (int) Math.hypot(height, width);
Log.e("hei", maxRradius + "");
if (flag) {
Animator animator = ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, maxRradius, 0);
animator.setDuration(1000);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mPuppet.setVisibility(View.GONE);
}
});
animator.start();
flag = false;
} else {
Animator animator = ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, 0, maxRradius);
animator.setDuration(1000);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mPuppet.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
flag = true;
}
}
}
上面三步走完,即可運(yùn)行程序,揭露動(dòng)畫隨即實(shí)現(xiàn),效果如下:

接著后面就進(jìn)入本文主題了;
2.使用揭露動(dòng)畫作為Activity的轉(zhuǎn)場(chǎng)動(dòng)畫
思路總結(jié):
1. MainActivity.java:
1.1. 實(shí)例化、聲明各種對(duì)象,注意:
根布局對(duì)象(用來控制整個(gè)布局),
揭露層對(duì)象指的是用于作揭露操作的純色的match_parent的View控件;
1.2. onCreate():完成findViewById()以及intent的構(gòu)建,F(xiàn)loatingActionButton的setOnClickListener;
1.3. onClick():計(jì)算fab的中心坐標(biāo),用于作為揭露動(dòng)畫的圓心;同時(shí)把這對(duì)坐標(biāo)put進(jìn)intent中,然后startActivity(intent);跳轉(zhuǎn)到下一個(gè)活動(dòng),同時(shí)把坐標(biāo)對(duì)傳過去;
1.4. createRevealAnimator():計(jì)算startRadius、endRadius,調(diào)用核心方法createCircularReveal()構(gòu)建出animator并做相關(guān)配置后return之;
注意:
這里的createCircularReveal()操作對(duì)象用的是揭露層純色View對(duì)象mPuppet0;
以及配置中用了animator.addListener(animatorListener0);添加一個(gè)動(dòng)畫監(jiān)聽器;--->> 1.5.
1.5. Animator.AnimatorListener animatorListener0
注意這里的思路:
?。。? onAnimationStart():收挽揭露動(dòng)畫開啟時(shí),揭露層setVisibility(View.VISIBLE);fab.setVisibility(View.INVISIBLE);
onAnimationEnd():收挽版揭露動(dòng)畫結(jié)束時(shí),mPuppet0.setVisibility(View.INVISIBLE);fab.setVisibility(View.VISIBLE);
!?。?
1.6. onRestart():回調(diào)方法,計(jì)算fab的中心坐標(biāo),用于作為揭露動(dòng)畫的圓心;
調(diào)用createRevealAnimator()創(chuàng)建并配置一個(gè)animator(--->> 1.4.),
然后開啟收挽版揭露動(dòng)畫,即animator.start();
2. next.java:
2.1. 實(shí)例化、聲明各種對(duì)象,注意:
根布局對(duì)象(用來控制整個(gè)布局),
揭露層對(duì)象指的是用于作揭露操作的純色的match_parent的View控件;
2.2. onCreate():完成findViewById(),
這里注意:
動(dòng)畫需要依賴于某個(gè)視圖才可啟動(dòng),這里依賴于根布局對(duì)象并且開辟一個(gè)子線程,
在子線程中g(shù)et坐標(biāo)對(duì),調(diào)用createRevealAnimator()創(chuàng)建并配置一個(gè)animator;--->> 2.3.
然后開啟展開版揭露動(dòng)畫,即animator.start();
2.3. createRevealAnimator():計(jì)算startRadius、endRadius,調(diào)用核心方法createCircularReveal()構(gòu)建出animator并做相關(guān)配置后return之;
注意這里的思路:
?。?!這里的createCircularReveal()操作對(duì)象用的是根布局對(duì)象content;
?。。。?!
(即先加載好整個(gè)布局,再把整個(gè)布局作為揭露對(duì)象從0徑到屏幕對(duì)角線徑揭露展開,
展開過程中揭露層純色view在最頂層,所以感覺是View在做展開而已,
而實(shí)際上并不是;展開完畢后,再把view層去掉,去掉之后下層的活動(dòng)內(nèi)容自然就顯示出來了。)
?。。。?!
以及配置中用了animator.addListener(animatorListener0);添加一個(gè)動(dòng)畫監(jiān)聽器;--->> 2.4.
2.4. Animator.AnimatorListener animatorListener1
注意這里的思路:
?。?!
onAnimationEnd():展開版揭露動(dòng)畫結(jié)束時(shí),
mPuppet.startAnimation(createAlphaAnimation());//調(diào)用透明度動(dòng)畫,絲滑效果-->>2.5.
mPuppet.setVisibility(View.INVISIBLE);//動(dòng)畫結(jié)束時(shí),揭露動(dòng)畫設(shè)置為不可見
?。?!
2.5. createAlphaAnimation():定義透明度動(dòng)畫,返回一個(gè)AlphaAnimation對(duì)象;
3. 兩個(gè)布局xml沒什么特別需要說的地方,
注意第一個(gè)xml的view要android:visibility="gone",以及按照渲染先后層次關(guān)系按序書寫控件即是;
4. styles.xml:android:windowAnimationStyle屬性置為null,取消掉Android默認(rèn)的轉(zhuǎn)場(chǎng)動(dòng)畫
<style name="noAnimTheme" parent="AppTheme">
<item name="android:windowAnimationStyle">@null</item>
</style>
5. AndroidManifest.xml:為參與的活動(dòng)添加剛剛設(shè)置好的主題;
<activity
android:name=".MainActivity"
android:theme="@style/noAnimTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".next"
android:theme="@style/noAnimTheme">
</activity>
最后上代碼了,不同的功能基本上都放在了不同的方法內(nèi)實(shí)現(xiàn),結(jié)合注釋應(yīng)該不難理解了~
MainActivity.java:
package com.lwp.justtest;
import ...
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
FloatingActionButton fab;
Intent intent;
private View content;//根布局對(duì)象(用來控制整個(gè)布局)
private View mPuppet0;//揭露層對(duì)象
private int centerX;
private int centerY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
content = findViewById(R.id.reveal_content0);
mPuppet0 = findViewById(R.id.view_puppet);
intent = new Intent(MainActivity.this, next.class);
fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int[] vLocation = new int[2];
fab.getLocationInWindow(vLocation);
centerX = vLocation[0] + fab.getMeasuredWidth() / 2;
centerY = vLocation[1] + fab.getMeasuredHeight() / 2;
intent.putExtra("cx",centerX);
intent.putExtra("cy",centerY);
startActivity(intent);
}
private Animator createRevealAnimator(int x, int y) {
float startRadius = (float) Math.hypot(content.getHeight(), content.getWidth());
float endRadius = fab.getMeasuredWidth() / 2 ;
//注意揭露動(dòng)畫開啟時(shí)是用根布局作為操作對(duì)象,關(guān)閉時(shí)用揭露層作為操作對(duì)象
Animator animator = ViewAnimationUtils.createCircularReveal(
mPuppet0, x, y,
startRadius,
endRadius);
animator.setDuration(500);
animator.setInterpolator(new AccelerateDecelerateInterpolator());//設(shè)置插值器
animator.addListener(animatorListener0);
return animator;
}
//定義動(dòng)畫狀態(tài)監(jiān)聽器_按下返回鍵版
private Animator.AnimatorListener animatorListener0 = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mPuppet0.setVisibility(View.VISIBLE);//按下返回鍵時(shí),動(dòng)畫開啟,揭露層設(shè)置為可見
fab.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
mPuppet0.setVisibility(View.INVISIBLE);
fab.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
};
//第二個(gè)活動(dòng)退回來時(shí),回調(diào)本方法
@Override
protected void onRestart() {
super.onRestart();
//動(dòng)畫需要依賴于某個(gè)視圖才可啟動(dòng),
// 這里依賴于根布局對(duì)象,并且開辟一個(gè)子線程,充分利用資源
content.post(new Runnable() {
@Override
public void run() {
int[] vLocation = new int[2];
fab.getLocationInWindow(vLocation);
centerX = vLocation[0] + fab.getMeasuredWidth() / 2;
centerY = vLocation[1] + fab.getMeasuredHeight() / 2;
Animator animator = createRevealAnimator(centerX, centerY);
animator.start();
}
});
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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/reveal_content0"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lwp.justtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Here is First Activity!"
android:textColor="@color/colorPrimaryDark"
android:textSize="30sp"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view_puppet"
android:background="@color/colorPrimaryDark"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:backgroundTint="@color/colorPrimary"
android:src="@drawable/map"
app:pressedTranslationZ="10dp" />
</FrameLayout>
next.java:
package com.lwp.justtest;
import ...
public class next extends AppCompatActivity {
private View content;//根布局對(duì)象(用來控制整個(gè)布局)
private View mPuppet;//揭露層對(duì)象
private int mX ;
private int mY ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);//先加載好整個(gè)布局,后面再用整個(gè)布局作為揭露動(dòng)畫的操作對(duì)象,揭露完畢后再去掉揭露層
content = findViewById(R.id.reveal_content);
mPuppet = findViewById(R.id.view_puppet);
//動(dòng)畫需要依賴于某個(gè)視圖才可啟動(dòng),
// 這里依賴于根布局對(duì)象,并且開辟一個(gè)子線程,充分利用資源
content.post(new Runnable() {
@Override
public void run() {
mX = getIntent().getIntExtra("cx", 0);
mY = getIntent().getIntExtra("cy", 0);
Animator animator = createRevealAnimator(mX, mY);
animator.start();
}
});
}
private Animator createRevealAnimator(int x, int y) {
float startRadius = 0;
float endRadius = (float) Math.hypot(content.getHeight(), content.getWidth());
Animator animator = ViewAnimationUtils.createCircularReveal(
content, x, y,
startRadius,
endRadius);
animator.setDuration(660);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
//判斷標(biāo)志位reversed,true則為添加返回鍵版動(dòng)畫監(jiān)聽器,false則為跳轉(zhuǎn)動(dòng)畫開啟版
// if (!reversed)
animator.addListener(animatorListener1);
return animator;
}
//定義動(dòng)畫狀態(tài)監(jiān)聽器_跳轉(zhuǎn)動(dòng)畫開啟版
private Animator.AnimatorListener animatorListener1 = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// content.setVisibility(View.VISIBLE);//跳轉(zhuǎn)進(jìn)來時(shí),(因?yàn)閒inish之前會(huì)將之設(shè)置為不可見,)
// 根布局要設(shè)置為可見,與finish部分的不可見相對(duì)應(yīng)
// mPuppet.setAlpha(1);
}
@Override
public void onAnimationEnd(Animator animation) {
mPuppet.startAnimation(createAlphaAnimation());
mPuppet.setVisibility(View.INVISIBLE);//動(dòng)畫結(jié)束時(shí),揭露動(dòng)畫設(shè)置為不可見
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
};
private AlphaAnimation createAlphaAnimation() {
AlphaAnimation aa = new AlphaAnimation(1,0);
aa.setDuration(400);
aa.setInterpolator(new AccelerateDecelerateInterpolator());//設(shè)置插值器
return aa;
}
}
next.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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/reveal_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lwp.justtest.next">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Here is Second Activity!"
android:textColor="@color/colorPrimaryDark"
android:textSize="30sp"
android:layout_gravity="center"/>
<View
android:id="@+id/view_puppet"
android:background="@color/colorPrimaryDark"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
res/values/styles.xml:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="noAnimTheme" parent="AppTheme">
<item name="android:windowAnimationStyle">@null</item>
</style>
</resources>
AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:theme="@style/noAnimTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".next"
android:theme="@style/noAnimTheme">
</activity>
</application>
最終效果圖:

本文的兩個(gè)demo就到此為止了,我相信以這個(gè)兩個(gè)demo為模板,結(jié)合筆者之前關(guān)于Material Design做的諸多筆記,應(yīng)該是可以做出不少很有趣的東西來的~