前幾篇中,我們說了安卓的補間動畫和插值器,這一篇,我們來寫2個例子。
- 【Android 動畫】動畫詳解之補間動畫(一)
- 【Android 動畫】動畫詳解之插值器(二)
- 【Android 動畫】動畫詳解之屬性動畫(三)
- 【Android 動畫】動畫詳解之仿微信檢視大圖效果(四)
- 【Android 動畫】動畫詳解之屬性動畫(五)
一、小球落地動畫
先上效果圖:
可以看到,小球是先加速下落,碰到底部後彈起,再下落,最後完全靜止,如果要手寫這個過程,還是相當麻煩的,有沒有簡單的辦法? 這裡就要用到我們第2篇中說到過的BounceInterpolator
插值器。 詳情請看【Android 動畫】動畫詳解之插值器(二)
translateAnimation = new TranslateAnimation(0, 0, 0, DensityUtils.dp2px(BallActivity.this, 400));
translateAnimation.setDuration(2000);
translateAnimation.setFillAfter(true);
translateAnimation.setInterpolator(new BounceInterpolator());
tvDemo.startAnimation(translateAnimation);
複製程式碼
二、仿微信檢視大圖效果
相信大家都有留意微信的檢視大圖動畫,它會由圖片當前在螢幕中的位置漸漸放大移動到螢幕中心,簡單來說的話就是一個縮放+透明度動畫。 先上效果圖:
之前在第一篇中,我們說過,縮放動畫的取值可以是具體數值、相對於自身、相對於父佈局這3種,這裡就需要使用相對於父佈局這種。首先,我們需要獲取點選按鈕在螢幕中的座標。先定義一個int資料用於存放座標,然後呼叫getLocationOnScreen
方法即可獲取該控制元件在螢幕中的座標
int[] location = new int[2];
btnTopLeft.getLocationOnScreen(location);
複製程式碼
然後,計算該座標相對於螢幕的百分比
pointx = getIntent().getIntExtra(POINTX, 0);
pointy = getIntent().getIntExtra(POINTY, 0);
DisplayMetrics metrics = getResources().getDisplayMetrics();
if (pointx == 0) {
pointXValue = 0.5f;
} else {
pointXValue = pointx / metrics.widthPixels;
}
if (pointy == 0) {
pointYValue = 0.5f;
} else {
pointYValue = pointy / metrics.heightPixels;
}
複製程式碼
新增動畫
AnimationSet animationSet = new AnimationSet(true);
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1f, 0, 1f, ScaleAnimation.RELATIVE_TO_PARENT,
pointXValue, ScaleAnimation.RELATIVE_TO_PARENT, pointYValue);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.setDuration(500);
animationSet.setFillAfter(true);
ivImg.startAnimation(animationSet);
複製程式碼
處理返回,重寫onBackPressed
方法,返回時,與進入的動畫正好相反
@Override
public void onBackPressed() {
AnimationSet animationSet = new AnimationSet(true);
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0, 1f, 0, ScaleAnimation.RELATIVE_TO_PARENT,
pointXValue, ScaleAnimation.RELATIVE_TO_PARENT, pointYValue);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.setDuration(500);
animationSet.setFillAfter(true);
animationSet.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
ImgActivity.super.onBackPressed();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
ivImg.startAnimation(animationSet);
}
複製程式碼
還需要處理預設的Activity切換動畫,以及Activity
的預設背景
startActivity(intent);
overridePendingTransition(0, 0);
複製程式碼
設定目標Activity的主題
<activity
android:name=".demo.ImgActivity"
android:theme="@style/transparent"></activity>
複製程式碼
<style name="transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
複製程式碼
當我們執行時會發現,動畫的起始位置是按鈕的左上角,原來使用getLocationOnScreen
獲取的是控制元件左上角的座標,所以我們需要加上控制元件寬高的1/2
。
TIP:由於此處所有按鈕的寬高都一樣,所以就取了同一個。
Intent intent = new Intent(WXPicActivity.this, ImgActivity.class);
int[] location = new int[2];
switch (view.getId()) {
case R.id.btn_top_left:
btnTopLeft.getLocationOnScreen(location);
break;
case R.id.btn_top_right:
btnTopRight.getLocationOnScreen(location);
break;
case R.id.btn_bottom_left:
btnBottomLeft.getLocationOnScreen(location);
break;
case R.id.btn_bottom_right:
btnBottomRight.getLocationOnScreen(location);
break;
case R.id.btn_center:
btnCenter.getLocationOnScreen(location);
break;
}
intent.putExtra(ImgActivity.POINTX, location[0] + btnCenter.getMeasuredWidth() / 2);
intent.putExtra(ImgActivity.POINTY, location[1] + btnCenter.getMeasuredHeight() / 2);
startActivity(intent);
overridePendingTransition(0, 0);
複製程式碼