學習一門技術或者看一篇文章最好的方式就是帶着問題去學習,這樣才能在過程當中有茅塞頓開、燈火闌珊的感受,記憶也會更深入。java
在 Android 開發中,動畫是必不可少的,它可讓 View 在變化的時候有一個過渡,避免用戶感受很突兀。所以,學好動畫,用好動畫是很是重要的,會給開發帶來不少快樂。android
Android 中動畫分爲幀動畫、View 動畫、屬性動畫三種,能夠在平常開發中根據需求的不一樣進行選擇,但基本上如今 90% 以上的均可以用屬性動畫解決,如今讓咱們來了解一下三種動畫。bash
逐幀動畫是一種常見的動畫形式(Frame By Frame),其原理是在「連續的關鍵幀」中分解動畫動做,也就是在時間軸的每幀上逐幀繪製不一樣的內容,使其連續播放而成動畫。 由於逐幀動畫的幀序列內容不同,不但給製做增長了負擔並且最終輸出的文件量也很大,但它的優點也很明顯:逐幀動畫具備很是大的靈活性,幾乎能夠表現任何想表現的內容,而它相似與電影的播放模式,很適合於表演細膩的動畫。app
在 Android 中提供了兩種方式爲 AnimationDrawable 添加幀:XML 定義的資源文件和 Java 代碼建立。下面咱們會逐一進行介紹。框架
Android 中的資源文件放在 /res 目錄下,對於動畫幀的資源須要當成一個 Drawable,因此須要把它放在 /res/Drawable 目錄下。而定義逐幀動畫很是簡單,在 drawable 文件夾下新建 xml 文件,在 <animation-list.../> 元素中使用 <item.../> 子元素定義動畫的所有幀,並制定各幀的持續時間便可。還能夠在 <animation-list.../> 元素中添加屬性,來設定逐幀動畫的屬性。ide
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<!-- 定義一個動畫幀,Drawable爲img0,持續時間50毫秒 -->
<item android:drawable="@drawable/uncheck_in1" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in2" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in3" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in4" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in5" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in6" android:duration="200"/>
</animation-list>
複製代碼
Java 代碼使用動畫post
// 經過逐幀動畫的資源文件得到AnimationDrawable示例
AnimationDrawable frameAnim = (AnimationDrawable) getResources().getDrawable(R.drawable.part5_frame1);
// 把AnimationDrawable設置爲ImageView的背景
mImageView.setBackgroundDrawable(frameAnim);
/**
*根據點擊事件控制動畫開啓,中止
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start:
frameAnim.start();
break;
case R.id.bt_stop:
frameAnim.stop();
break;
}
}
複製代碼
在 Android 中,除了能夠經過 XML 文件定義一個逐幀動畫以外,還能夠經過 AnimationDrawable.addFrame() 方法爲 AnimationDrawable 添加動畫幀。
效果圖和上面的同樣,這裏就不放了,直接上代碼。學習
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_part5_frame_java);
mImageView = findViewById(R.id.iv_frame1);
Button bt_stop = findViewById(R.id.bt_stop);
Button bt_start = findViewById(R.id.bt_start);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
frameAnim = new AnimationDrawable();
// 爲AnimationDrawable添加動畫幀
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in1), 200);
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in2), 200);
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in3), 200);
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in4), 200);
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in5), 200);
frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in6), 200);
frameAnim.setOneShot(false);
mImageView.setBackground(frameAnim);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start:
if (frameAnim != null && !frameAnim.isRunning()) {
frameAnim.start();
}
break;
case R.id.bt_stop:
if (frameAnim != null && frameAnim.isRunning()) {
frameAnim.stop();
}
break;
}
}
複製代碼
使用幀動畫的時候要注意不要使用過大的圖片,會引發 OOM。動畫
View 動畫框架只能用於 Views。 比較容易設置和能知足許多應用程序的須要。View 動畫框架中一共提供了 AlphaAnimation(透明度動畫)、RotateAnimation(旋轉動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(平移動畫)四種類型的補間動畫;而且 View 動畫框架還提供了動畫集合類(AnimationSet),經過動畫集合類(AnimationSet)能夠將多個補間動畫以組合的形式顯示出來。View 動畫只是顯示效果,View 的實際屬性及位置並未發生變化。ui
先看效果圖
在 /res 目錄下新建 anim 文件夾,在 anim 文件夾下新建 xml 文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 透明度變化,從 1 到 0-->
<alpha
android:duration="5000"
android:fromAlpha="1.0"
android:toAlpha="0.0"
/>
<!-- 縮放,寬高都是從 1 到 0
pivotX、pivotY 表明縮放中心點的橫豎座標
interpolator 表明動畫模式,我設置爲先加速、後減速-->
<scale
android:duration="5000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0"
/>
<!-- 平移動畫,從左上角到右下角-->
<translate
android:duration="5000"
android:fromXDelta="150"
android:fromYDelta="150"
android:toXDelta="200"
android:toYDelta="200"/>
<!-- 旋轉動畫,fromDegrees 初始角度
結束角度 toDegrees-->
<rotate
android:duration="5000"
android:fromDegrees="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="+360"/>
</set>
複製代碼
在代碼中給 view 添加動畫
ImageView iv_bee=findViewById(R.id.iv_bee);
// 設置動畫資源
Animation loadAnimation =AnimationUtils.loadAnimation(this,R.anim.part5view_anim1);
//動畫結束後保持最後的狀態
loadAnimation.setFillAfter(true);
//給 view 添加動畫
iv_bee.startAnimation(loadAnimation);
複製代碼
與屬性動畫相比 View 動畫存在一個缺陷,View 動畫改變的只是 View 的顯示,而沒有改變View的響應區域,而且 View 動畫只能對 View 作四種類型的補間動畫,所以在 Android3.0 及其後續版本中添加了屬性動畫框架。
屬性動畫理論知識有不少講解,能夠具體看下面的文章
HenCoder Android 自定義 View 1-6:屬性動畫 Property Animation(上手篇)
我這裏就不講理論了,直接擼效果
很簡單的一個數字滾動效果,用屬性動畫也很容易作出來,幾行代碼搞定
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_part5_object_anim);
mTv_object = findViewById(R.id.tv_object);
Button bt_start=findViewById(R.id.bt_start);
bt_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showMoneyAnim(1,500);
}
});
}
private void showMoneyAnim(int mStartValue, int mEndValue) {
ValueAnimator animator = ValueAnimator.ofInt(mStartValue, mEndValue);
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTv_object.setText(animation.getAnimatedValue().toString());
}
});
animator.start();
}
複製代碼
具體翻轉代碼,分爲上半段和下半段動畫
public class Part4AnimationActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_part4_animation);
final ImageView iv_animation=findViewById(R.id.iv_animation);
iv_animation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
applyRotation(false,iv_animation,0,-90);
}
});
}
/**
* 設置一個新的三維旋轉的容器視圖。只翻通常,而後設置新的現實內容
*
* @param zheng
* 一個判斷機制 若是爲true 則向右翻轉,若是false則向左翻轉
* @param view
* 傳入的片斷
* @param start
* 起始位置
* @param end
* 結束位置
*/
public void applyRotation(final boolean zheng, final View view,
final float start, final float end) {
// Find the center of the container
final float centerX = view.getWidth() / 2.0f;
final float centerY = view.getHeight() / 2.0f;
// Create a new 3D rotation with the supplied parameter
// The animation listener is used to trigger the next animation
final Util_Rotate3DAnimation rotation = new Util_Rotate3DAnimation(
start, end, centerX, centerY, 310.0f, true);
rotation.setDuration(500);
rotation.setFillAfter(true);
rotation.setInterpolator(new AccelerateInterpolator());
rotation.setAnimationListener(new DisplayNextView(zheng, view));// 添加監聽執行現實內容的切換
view.startAnimation(rotation);// 執行上半場翻轉動畫
}
/**
* 執行完上半部分旋轉以後,設置要顯示的新的View而後繼續執行下半部分旋轉
*/
private final class DisplayNextView implements Animation.AnimationListener {
private final boolean mPosition;
private final View mView;
private DisplayNextView(boolean zheng, View view) {
mPosition = zheng;
mView = view;
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
mView.post(new SwapViews(mPosition, mView));// 添加新的View
}
public void onAnimationRepeat(Animation animation) {
}
}
/**
* 添加要顯示的新的View,並執行下半部分的旋轉操做
*/
private final class SwapViews implements Runnable {
private final boolean mPosition;
private final ImageView mView;
public SwapViews(boolean position, View view) {
mPosition = position;
mView = (ImageView) view;
}
public void run() {
final float centerX = mView.getWidth() / 2.0f;
final float centerY = mView.getHeight() / 2.0f;
Util_Rotate3DAnimation rotation;
if (mPosition) {
rotation = new Util_Rotate3DAnimation(-90, 0, centerX, centerY,
310.0f, false);
} else {
rotation = new Util_Rotate3DAnimation(90, 0, centerX, centerY,
310.0f, false);
}
mView.setImageResource(R.drawable.head2);
rotation.setDuration(500);
rotation.setFillAfter(true);
rotation.setInterpolator(new DecelerateInterpolator());
mView.startAnimation(rotation);
}
}
}
複製代碼
文章已經讀到末尾了,不知道最初的幾個問題你都會了嗎?若是不會的話?能夠再針對不會的問題進行精讀哦!答案都在文中,相信你確定能夠解決的!