android進階4step1:Android動畫處理與自定義View——轉場動畫
以下都需要執行在5.0以上
一、揭露動畫效果
參考:使用Circular Reveal為你的應用新增揭露動畫效果
最主要的類Circular Reveal
官方將這一動畫稱為揭露效果,它在官網中的描述是這樣的:
當您顯示或隱藏一組 UI 元素時,揭露動畫可為使用者提供視覺連續性。[ViewAnimationUtils.createCircularReveal()](https://developer.android.com/reference/android/view/ViewAnimationUtils.html?hl=zh-cn#createCircularReveal(android.view.View
, int, int, float, float))
方法讓您能夠為裁剪區域新增動畫以揭露或隱藏檢視。
很明顯,我們使用ViewAnimationUtils.createCircularReveal()方法就能達到基本的揭露動畫效果了。那麼我們就直接開始看一下這個方法到底需要哪些引數吧
Animator createCircularReveal (View view, // The View will be clipped to the animating circle. int centerX, // The x coordinate of the center of the animating circle, relative to view int centerY, // The y coordinate of the center of the animating circle, relative to view float startRadius, // The starting radius of the animating circle. float endRadius // The ending radius of the animating circle. )
ViewAnimationUtils.createCircularReveal()方法所執行的效果,就是將一個View裁剪成圓,然後從圓心逐漸揭露展現檢視。
引數 | 引數說明 |
---|---|
view | 要執行動畫效果的View |
centerX | 圓心x座標 |
centerY | 圓心y座標 |
startRadius | 開始時的圓半徑 |
endRadius | 結束時的圓半徑 |
其實引數都是比較容易理解的,主要是涉及到了動畫開始的x,y座標,以及圓形揭露的半徑變化startRadius->endRadius。
在此我就以最上面的那個效果圖為例,對createCircularReveal ()的使用進行一個簡單的引入吧。
簡單使用:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;
public class MainActivity extends AppCompatActivity {
private View mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mView = findViewById(R.id.view);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_enter:
revealEnter();
break;
case R.id.btn_exit:
revealExit();
break;
}
}
/**
* 進入動畫
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void revealEnter() {
//獲取檢視的寬度
int w = mView.getWidth();
int h = mView.getHeight();
//設定基準點(園的中心點)的位置 從左上角開始(0,0)
//(w,h) 應該在檢視的右下角
int cx = w;
int cy = h;
//Math.hypot() 函式返回它的所有引數的平方和的平方根,即:檢視的對角線
//開始的圓的半徑
int r = (int) Math.hypot(w, h);
Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, 0, r);
//設定顯示動畫的時間間隔
animator.setDuration(2000);
mView.setVisibility(View.VISIBLE);
animator.start();
}
/**
* 離開動畫
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void revealExit() {
//獲取檢視的寬度
int w = mView.getWidth();
int h = mView.getHeight();
//設定基準點(園的中心點)的位置 從左上角開始(0,0)
int cx = w;
int cy = h;
//Math.hypot() 函式返回它的所有引數的平方和的平方根,即:檢視的對角線
//開始的圓的半徑
int r = (int) Math.hypot(w, h);
/**
*
*/
Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, r, 0);
//設定顯示動畫的時間間隔
animator.setDuration(2000);
animator.start();
//當動畫結束後讓檢視不可見
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mView.setVisibility(View.INVISIBLE);
}
});
}
}
二、轉場動畫(場景間 同一個Activity中)
Transition框架核心Scene、Transition和TransitionManager類
-
Scene:場景 (定義了介面當前的狀態資訊,儲存了佈局中所有View的屬性值)
其中Scene是一個容器,就是放置你定義的佈局,而真正去做場景之間切換這個動作是Transition框架中TransitionManager 呼叫其中go方法或者transitionTo方法完成場景之間切換,而真正建立具體動畫交由Transition子類來完成,開始動畫交給Transition來執行。
轉:Android場景動畫(Scene)Scene.getSceneForLayout() 引數介紹如下:
- sceneRoot 表示從什麼地方開始切換場景。
- layoutId 切換到什麼場景的佈局檔案,比如上述例子中生成Scene2例項,layoutId 就是場景2中的佈局。
- context 上下文
-
Transition:轉換
當一個場景改變的時候,transition主要負責:捕獲每個View在開始場景和結束場景時的狀態(各種屬性值);
根據兩個場景(開始和結束)之間的區別自動建立一個Animator。
監聽一個容器內部有控制元件的狀態發生改變後執行的動畫
一個有四種動畫效果:
- Slide 劃入
- Explode 爆炸
- Fade 隱藏
- changeBounds 位置與大小變化
-
TransitionManager:負責場景之間的跳轉和新增效果
- 這個類將
Sence
與Transition
關聯了起來,大多數情況下的場景變化都會使用AutoTransition(預設動畫)
。只有當應用程式需要不同的轉換行為時,才需要指定其他的Transition來滿足特定的場景需求。
- setTransition(Scene scene, Transition transition)
設定需要的場景與過渡動畫
- setTransition(Scene fromScene, Scene toScene, Transition transition)
設定起始場景和結束場景與過渡動畫
- go(Scene scene)
切換到指定的場景
- go(Scene scene, Transition transition)
切換到指定的場景以及所使用的過渡動畫,transition如果傳了null,那麼就沒有了過渡動畫。
- beginDelayedTransition(ViewGroup sceneRoot, Transition transition)
可以自定義場景過渡的方法,呼叫此方法時,TransitionManager會捕獲sceneRoot中View的屬性值,然後發出請求以在下一幀上進行轉換。那時候,sceneRoot中的新值將被捕獲,變化的過程將會以動畫的形式展現出來。我們沒有必要建立一個新的Scene,因為這個方法主要是用來展現當前場景到下一幀的過渡效果。
- void endTransitions (ViewGroup sceneRoot)
結束指定場景根目錄在準備/正在進行的轉換。
更詳細的解釋,請移步官方API。
示例程式碼:
效果:
自定義動畫效果:在res目錄中建立transition資料夾 建立transition.xml檔案
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<!--第一種動畫效果-->
<changeImageTransform android:duration="1000">
<!--指定圖片控制元件的id-->
<targets android:targetId="@id/image" />
</changeImageTransform>
<!--第二種動畫效果 淡入淡出-->
<fade android:duration="1000" android:startDelay="1000">
</fade>
</transitionSet>
實現類
public class SceneActivity extends AppCompatActivity {
private Scene mOverViewScene;
private Scene mInfoScene;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scene);
//根佈局
ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
//搭建第一個場景
mOverViewScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_overview, getBaseContext());
//搭建第二個場景
mInfoScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_info, getBaseContext());
//首先跳轉到第一個場景
TransitionManager.go(mOverViewScene);
}
//點選事件實現場景的跳轉邏輯
public void onClick(View view) {
switch (view.getId()) {
//點選info圖示時
case R.id.btnInfo:
//載入自定義的跳轉動畫
Transition transition = TransitionInflater.from(getBaseContext())
.inflateTransition(R.transition.transition);
TransitionManager.go(mInfoScene, transition);
//預設是AutoTransition
//TransitionManager.go(mInfoScene);
break;
//點選close圖示時
case R.id.btnClose:
TransitionManager.go(mOverViewScene);
break;
}
}
}
三、Activity間的轉場動畫
轉:android 學習使用Activity轉場動畫及shareElement
轉場動畫(Activity Transition)基本介紹
Android 5.0 提供了三種Transition型別
- 進入:決定Activity中的所有的檢視怎麼進入螢幕。
- 退出:決定一個Activity中的所有檢視怎麼退出螢幕。
- 共享元素(shareElement):決定兩個activities之間的過渡,怎麼共享(它們)的檢視。
進入和退出包含如下動畫效果
- explode(分解) – 從螢幕中間進或出
- slide(滑動) - 從螢幕邊緣進或出地
- fade(淡出) –通過改變螢幕上檢視的不透明度達到新增或者移除檢視的效果
共享元素包含如下動畫效果
- changeBounds - 改變目標檢視的佈局邊界
- changeClipBounds - 裁剪目標檢視邊界
- changeTransform - 改變目標檢視的縮放比例和旋轉角度
- changeImageTransform - 改變目標圖片的大小和縮放比例
Transition 與 Activity的跳轉動畫有以下幾個
- setEnterTransition 進入的動畫
- setExitTransition 退出的動畫
- setReturnTransition 返回的動畫
-
setReenterTransition 重入的動畫
示例:
第一個Activity
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onClick(View view) {
int resId = -1;
switch (view.getId()) {
case R.id.iv1:
resId = R.drawable.pic1;
break;
case R.id.iv2:
resId = R.drawable.pic2;
break;
case R.id.iv3:
resId = R.drawable.pic3;
break;
case R.id.iv4:
resId = R.drawable.pic4;
break;
}
/**
* 每點選一張圖片
* 都會將這一張圖片的資源id傳出去
*/
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("resId", resId);
//建立transition
Transition transition = new Explode();
//指定狀態列不變(指定某一個控制元件不使用動畫)(排除某個元素不在轉場動畫中)
transition.excludeTarget(android.R.id.statusBarBackground, true);
//設定進場動畫
getWindow().setEnterTransition(transition);
//設定離場動畫
getWindow().setExitTransition(transition);
//重進動畫
getWindow().setReenterTransition(transition);
//設定共享元素進場動畫
getWindow().setSharedElementEnterTransition(transition);
//設定共享元素(當前view 和 共享元素id 根據這個id來匹配)
Pair<View, String> shareElement = Pair.create(view, "img");
//makeSceneTransitionAnimation 可以不設定或者設定多個共享元素
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, shareElement);
//通過toBundle方法傳給startActivity
startActivity(intent, options.toBundle());
}
}
第二個Activity
public class SecondActivity extends Activity {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//拿到傳來的圖片資源id
int resId = getIntent().getExtras().getInt("resId");
ImageView iv = findViewById(R.id.iv);
//共享元素的id
iv.setTransitionName("img");
//設定給當前佈局的ImageView
iv.setImageResource(resId);
Transition transition = new Explode();
//指定狀態列不變(指定某一個控制元件不使用動畫)(排除它)
transition.excludeTarget(android.R.id.statusBarBackground, true);
//設定進場動畫
getWindow().setEnterTransition(transition);
//設定離場動畫
getWindow().setExitTransition(transition);
}
}
除了可以在程式碼中開啟轉場還可以定義在Style中
啟動轉場
<style name="BaseAppTheme" parent="android:Theme.Material">
<!– 啟動視窗內容轉場 -->
<item name="android:windowContentTransitions">true</item>
<!– 視窗進入/離開時演示的動畫 -->
<item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item>
<!– 共享元素進入/離開時演示的動畫 -->
<item name="android:windowSharedElementEnterTransition">
@transition/change_image_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_image_transform</item>
</style>