import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.Toast;
public class ActivityAnimationUtil
{
private Context context;
private Activity activity;
public static boolean IS_V2_3 = false;
public ActivityAnimationUtil(Context context)
{
this.context = context;
this.activity = (Activity) context;
}
public void check()
{
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD)
{
IS_V2_3 = true;
}
}
@SuppressLint("ShowToast")
public void startActivity(Intent intent, StyleIn in)
{
switch (in) {
case FADE:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
break;
case FLIPHORIZONTAL:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.flip_horizontal_in, R.anim.flip_horizontal_out);
break;
case FLIPVERTICAL:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.flip_vertical_in, R.anim.flip_vertical_out);
break;
case DISAPPEARTOPLEFT:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.disappear_top_left_in, R.anim.disappear_top_left_out);
break;
case APPEARBOTTOMRIGHT:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.appear_bottom_right_in, R.anim.appear_bottom_right_out);
break;
case SLIDELEFTRIGHT:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
break;
case SLIDETOPBOTTOM:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
break;
case SPILT:
check();
if (IS_V2_3)
{
SplitAnimation.startActivity(activity, intent);
} else
{
Toast.makeText(context, "手机系统版本过低(不得低于2.3),不支持当前动画此效果!", Toast.LENGTH_SHORT);
}
break;
case UNZOOM:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.unzoom_in, R.anim.unzoom_out);
break;
case STACK:
context.startActivity(intent);
activity.overridePendingTransition(R.anim.open_next, R.anim.close_main);
break;
default:
break;
}
}
public void backActivity(StyleOut out)
{
switch (out) {
case B_FADE:
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
break;
case B_FLIPHORIZONTAL:
activity.overridePendingTransition(R.anim.flip_horizontal_in, R.anim.flip_horizontal_out);
break;
case B_FLIPVERTICAL:
activity.overridePendingTransition(R.anim.flip_vertical_in, R.anim.flip_vertical_out);
break;
case B_DISAPPEARTOPLEFT:
activity.overridePendingTransition(R.anim.appear_top_left_in, R.anim.appear_top_left_out);
break;
case B_APPEARBOTTOMRIGHT:
activity.overridePendingTransition(R.anim.disappear_bottom_right_in, R.anim.disappear_bottom_right_out);
break;
case B_SLIDELEFTRIGHT:
activity.overridePendingTransition(R.anim.push_left_in, R.anim.push_right_out);
break;
case B_SLIDETOPBOTTOM:
activity.overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_top_out);
break;
case B_UNZOOM:
activity.overridePendingTransition(R.anim.unzoom_in, R.anim.unzoom_out);
break;
case B_STACK:
activity.overridePendingTransition(R.anim.open_main, R.anim.close_next);
break;
default:
break;
}
}
}
SPLIT动画工具类:
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
/**
*
* 用代码实现类似微信开门效果
*/
@SuppressLint("NewApi")
public class SplitAnimation
{
public static Bitmap mBitmap = null;
private static int[] mLoc1;
private static int[] mLoc2;
private static ImageView mTopImage;
private static ImageView mBottomImage;
private static AnimatorSet mSetAnim;
/**
* Start a new Activity with a Split animation
*
* @param currActivity
* The current Activity
* @param intent
* The Intent needed tot start the new Activity
* @param splitYCoord
* The Y coordinate where we want to split the Activity on the animation. -1 will split the Activity equally
*/
public static void startActivity(Activity currActivity, Intent intent, int splitYCoord)
{
// Preparing the bitmaps that we need to show
prepare(currActivity, splitYCoord);
currActivity.startActivity(intent);
currActivity.overridePendingTransition(0, 0);
}
/**
* Start a new Activity with a Split animation right in the middle of the Activity
*
* @param currActivity
* The current Activity
* @param intent
* The Intent needed tot start the new Activity
*/
public static void startActivity(Activity currActivity, Intent intent)
{
startActivity(currActivity, intent, -1);
}
/**
* Preparing the graphics on the destination Activity. Should be called on the destination activity on Activity#onCreate() BEFORE setContentView()
*
* @param destActivity
* the destination Activity
*/
public static void prepareAnimation(final Activity destActivity)
{
mTopImage = createImageView(destActivity, mBitmap, mLoc1);
mBottomImage = createImageView(destActivity, mBitmap, mLoc2);
}
/**
* Start the animation the reveals the destination Activity Should be called on the destination activity on Activity#onCreate() AFTER setContentView()
*
* @param destActivity
* the destination Activity
* @param duration
* The duration of the animation
* @param interpolator
* The interpulator to use for the animation. null for no interpulation.
*/
public static void animate(final Activity destActivity, final int duration, final TimeInterpolator interpolator)
{
// Post this on the UI thread's message queue. It's needed for the items to be already measured
new Handler().post(new Runnable()
{
@Override
public void run()
{
mSetAnim = new AnimatorSet();
mTopImage.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mBottomImage.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mSetAnim.addListener(new Animator.AnimatorListener()
{
@Override
public void onAnimationStart(Animator animation)
{
}
@Override
public void onAnimationEnd(Animator animation)
{
clean(destActivity);
}
@Override
public void onAnimationCancel(Animator animation)
{
clean(destActivity);
}
@Override
public void onAnimationRepeat(Animator animation)
{
}
});
// Animating the 2 parts away from each other
Animator anim1 = ObjectAnimator.ofFloat(mTopImage, "translationY", mTopImage.getHeight() * -1);
Animator anim2 = ObjectAnimator.ofFloat(mBottomImage, "translationY", mBottomImage.getHeight());
if (interpolator != null)
{
anim1.setInterpolator(interpolator);
anim2.setInterpolator(interpolator);
}
mSetAnim.setDuration(duration);
mSetAnim.playTogether(anim1, anim2);
mSetAnim.start();
}
});
}
/**
* Start the animation that reveals the destination Activity Should be called on the destination activity on Activity#onCreate() AFTER setContentView()
*
* @param destActivity
* the destination Activity
* @param duration
* The duration of the animation
*/
public static void animate(final Activity destActivity, final int duration)
{
animate(destActivity, duration, new DecelerateInterpolator());
}
/**
* Cancel an in progress animation
*/
public static void cancel()
{
if (mSetAnim != null)
mSetAnim.cancel();
}
/**
* Clean stuff
*
* @param activity
* The Activity where the animation is occurring
*/
private static void clean(Activity activity)
{
if (mTopImage != null)
{
mTopImage.setLayerType(View.LAYER_TYPE_NONE, null);
try
{
// If we use the regular removeView() we'll get a small UI glitch
activity.getWindowManager().removeViewImmediate(mBottomImage);
} catch (Exception ignored)
{
}
}
if (mBottomImage != null)
{
mBottomImage.setLayerType(View.LAYER_TYPE_NONE, null);
try
{
activity.getWindowManager().removeViewImmediate(mTopImage);
} catch (Exception ignored)
{
}
}
mBitmap = null;
}
/**
* Preparing the graphics for the animation
*
* @param currActivity
* the current Activity from where we start the new one
* @param splitYCoord
* The Y coordinate where we want to split the activity. -1 will split the activity equally
*/
private static void prepare(Activity currActivity, int splitYCoord)
{
// Get the content of the activity and put in a bitmap
View root = currActivity.getWindow().getDecorView().findViewById(android.R.id.content);
root.setDrawingCacheEnabled(true);
mBitmap = root.getDrawingCache();
// If the split Y coordinate is -1 - We'll split the activity equally
splitYCoord = (splitYCoord != -1 ? splitYCoord : mBitmap.getHeight() / 2);
if (splitYCoord > mBitmap.getHeight())
throw new IllegalArgumentException("Split Y coordinate [" + splitYCoord + "] exceeds the activity's height [" + mBitmap.getHeight() + "]");
// Set the location to put the 2 bitmaps on the destination activity
mLoc1 = new int[] { 0, splitYCoord, root.getTop() };
mLoc2 = new int[] { splitYCoord, mBitmap.getHeight(), root.getTop() };
}
/**
* Creating the an image, containing one part of the animation on the destination activity
*
* @param destActivity
* The destination activity
* @param bmp
* The Bitmap of the part we want to add to the destination activity
* @param loc
* The location this part should be on the screen
* @return
*/
private static ImageView createImageView(Activity destActivity, Bitmap bmp, int loc[])
{
MyImageView imageView = new MyImageView(destActivity);
imageView.setImageBitmap(bmp);
imageView.setImageOffsets(bmp.getWidth(), loc[0], loc[1]);
WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP;
windowParams.x = 0;
windowParams.y = loc[2] + loc[0];
windowParams.height = loc[1] - loc[0];
windowParams.width = bmp.getWidth();
windowParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
windowParams.format = PixelFormat.TRANSLUCENT;
windowParams.windowAnimations = 0;
destActivity.getWindowManager().addView(imageView, windowParams);
return imageView;
}
/**
* MyImageView Extended ImageView that draws just part of an image, base on start/end position
*/
private static class MyImageView extends ImageView
{
private Rect mSrcRect;
private Rect mDstRect;
private Paint mPaint;
public MyImageView(Context context)
{
super(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
/**
* Setting the bitmap offests to control the visible area
*
* @param width
* The bitmap image
* @param bmp
* The start Y position
* @param loc
* The end Y position
* @return
*/
public void setImageOffsets(int width, int startY, int endY)
{
mSrcRect = new Rect(0, startY, width, endY);
mDstRect = new Rect(0, 0, width, endY - startY);
}
@Override
protected void onDraw(Canvas canvas)
{
Bitmap bm = null;
Drawable drawable = getDrawable();
if (null != drawable && drawable instanceof BitmapDrawable)
{
bm = ((BitmapDrawable) drawable).getBitmap();
}
if (null == bm)
{
super.onDraw(canvas);
} else
{
canvas.drawBitmap(bm, mSrcRect, mDstRect, mPaint);
}
}
}
}
动画进入枚举:
package com.functiontest.key;
public enum StyleIn
{
/** 渐变动画 */
FADE,
/** 水平伸缩效果 */
FLIPHORIZONTAL,
/** 垂直伸缩 */
FLIPVERTICAL,
/** 左上角进入动画 */
DISAPPEARTOPLEFT,
/** 右下角进入动画 */
APPEARBOTTOMRIGHT,
/** 水平平移效果 */
SLIDELEFTRIGHT,
/** 垂直平移效果 */
SLIDETOPBOTTOM,
/** 开门效果 */
SPILT,
/** 缩放动画进入 */
UNZOOM,
/** 层叠效果进入 */
STACK
}
动画退出枚举:
package com.functiontest.key;
public enum StyleOut
{
/** 渐变动画 */
B_FADE,
/** 水平伸缩效果 */
B_FLIPHORIZONTAL,
/** 垂直伸缩 */
B_FLIPVERTICAL,
/** 左上角进入动画 */
B_DISAPPEARTOPLEFT,
/** 右下角进入动画 */
B_APPEARBOTTOMRIGHT,
/** 水平平移效果 */
B_SLIDELEFTRIGHT,
/** 垂直平移效果 */
B_SLIDETOPBOTTOM,
/** 缩放动画进入 */
B_UNZOOM,
/** 层叠效果进入 */
B_STACK
}
工具类的使用方法:
第一个页面:
import com.functiontest.key.StyleIn;
import com.functiontest.uitl.ActivityAnimationUtil;
import com.functiontest.uitl.SplitAnimation;
import net.tsz.afinal.FinalActivity;
import net.tsz.afinal.annotation.view.ViewInject;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends FinalActivity
{
@ViewInject(id = R.id.btn_next, click = "onClick")
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view)
{
switch (view.getId()) {
case R.id.btn_next:
Intent intent = new Intent(MainActivity.this, secondActivity.class);
ActivityAnimationUtil animation = new ActivityAnimationUtil(this);
animation.startActivity(intent, StyleIn.SPILT);
break;
default:
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
第二个页面:
import com.functiontest.key.StyleOut;
import com.functiontest.uitl.ActivityAnimationUtil;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import net.tsz.afinal.FinalActivity;
import net.tsz.afinal.annotation.view.ViewInject;
public class secondActivity extends FinalActivity
{
@ViewInject(id = R.id.btn_back, click = "onClick")
public Button button;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.second_main);
}
public void onClick(View view)
{
switch (view.getId()) {
case R.id.btn_back:
back();
break;
default:
break;
}
}
public void back()
{
this.finish();
ActivityAnimationUtil animation = new ActivityAnimationUtil(this);
animation.backActivity(StyleOut.B_STACK);
}
@Override
public void onBackPressed()
{
super.onBackPressed();
back();
}
}
文件下载地址:http://pan.baidu.com/s/1i3eIufb