您的位置:首页 > 移动开发 > Android开发

Android开发之tween(补间动画)动画及其使用场景(界面切换、弹窗等)详解

2014-12-22 21:47 656 查看
在Android开发中,我们常见一些很绚丽的动画效果。这些动画效果使得我们的应用用起来非常的绚丽。那么今天就来讲讲Android开发中,常用的动画效果吧。

在Android开发中,有帧动画和补间动画两种

1、逐帧动画是在时间帧上逐帧绘制帧内容,由于是一帧一帧的画,所以逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容。但是在开发中,我们不常用这个动画。

2、与逐帧动画相比,补间动画具有以下几个特点:首先,制作方法简单方便。只需要为动画的第一个关键帧和最后一个关键帧创建内容,两个关键帧之间帧的内容由Flash自动生成,不需要人为处理。其次,相对于逐帧动画来说,补间动画更为连贯自然。因为逐帧动画是由手工控制,帧与帧之间的过渡很可能会不自然、不连贯,而补间动画除了两个关键帧由手工控制外,中间的帧都由Flash自动生成,技术含量很高,因此过渡更为自然连贯。最后,相对于逐帧动画来说,补间动画的文件更小,占用内存少。

今天,我们详细的讲解补间动画。所谓补间动画,就是在两个画面跳转的时候,执行的动画。在Android开发中,我们在activity切换,fragment切换,dialog、PopupWindow以及使用WindowManager的时候,我们都会有需要动画来是的切换或者展示效果更佳的绚丽。补间动画有四种:平移、缩放、旋转、渐变。

一、在代码中实现动画效果,这里博主自定义了一个Animation提供者,直接上代码:

/**
* @ClassName: FreedomAnimationUtils
* @author victor_freedom (x_freedom_reddevil@126.com)
* @createddate 2014年12月22日 下午9:57:21
* @Description: 动画工具提供者
*/
public class FreedomAnimationUtils {

/**
* @Title: getRotateAnimation
* @Description: 旋转动画
* @param fromDegrees
*            起始角度
* @param toDegrees
*            结束角度
* @param pivotXType
*            相对于什么位置(Animation.RELATIVE_TO_SELF(相对于父控件),
*            Animation.RELATIVE_TO_SELF(相对于自己),Animation.ABSOLUTE(绝对位置))
* @param pivotXValue
*            以什么为中心点
* @param pivotYType
*            同上
* @param pivotYValue
*            同上
* @param durationMillis
*            维持时间
* @return
* @throws
*/
public static Animation getRotateAnimation(float fromDegrees,
float toDegrees, int pivotXType, float pivotXValue, int pivotYType,
float pivotYValue, long durationMillis) {
RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
// 重复模式:1、重新开始;2、从尾开始
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatMode(Animation.REVERSE);
// 维持时间
rotate.setDuration(durationMillis);
// 完毕之后是否保持状态
rotate.setFillAfter(true);
return rotate;
}

/**
* @Title: getAlphaAnimation
* @Description: 透明度
* @param fromAlpha
* @param toAlpha
* @param durationMillis
* @return
* @throws
*/
public static Animation getAlphaAnimation(float fromAlpha, float toAlpha,
long durationMillis) {
AlphaAnimation alpha = new AlphaAnimation(fromAlpha, toAlpha);
// 重复次数
alpha.setRepeatCount(2);
// 重复模式:1、重新开始;2、从尾开始
alpha.setRepeatMode(Animation.RESTART);
alpha.setRepeatMode(Animation.REVERSE);
// 维持时间
alpha.setDuration(durationMillis);
// 完毕之后是否保持状态
alpha.setFillAfter(true);
return alpha;
}

/**
* @Title: getScaleAnimation
* @Description: 缩放动画
* @param fromX
*            起始大小
* @param toX
*            缩放后大小
* @param fromY
*            起始大小
* @param toY
*            缩放后大小
* @param pivotXType
*            缩放参照物,相对于哪一个位置(Animation.ABSOLUTE,
*            Animation.RELATIVE_TO_SELF,or Animation.RELATIVE_TO_PARENT);
* @param pivotXValue
*            缩放的时候以哪一个位置为中心点,一般写0.5f,相对于控件中央
* @param pivotYType
* @param pivotYValue
* @param durationMillis
* @return
* @throws
*/
public static Animation getScaleAnimation(float fromX, float toX,
float fromY, float toY, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue, long durationMillis) {
ScaleAnimation scale = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
scale.setDuration(durationMillis);
return scale;
}

/**
* @Title: getTranslateAnimation
* @Description: TODO
* @param fromXDelta
*            这个参数表示动画开始的点离当前View X坐标上的差值;
* @param toXDelta
*            这个参数表示动画结束的点离当前View X坐标上的差值;
* @param fromYDelta
*            这个参数表示动画开始的点离当前View Y坐标上的差值;
* @param toYDelta
*            这个参数表示动画开始的点离当前View Y坐标上的差值;
* @param durationMillis
* @return
* @throws
*/
public static Animation getTranslateAnimation(float fromXDelta,
float toXDelta, float fromYDelta, float toYDelta,
long durationMillis) {
TranslateAnimation translate = new TranslateAnimation(fromXDelta,
toXDelta, fromYDelta, toYDelta);
translate.setDuration(durationMillis);
translate.setFillAfter(true);
return translate;
}

/**
* @Title: getTranslateAnimations
* @Description: TODO
* @param fromXType
*            第一个参数是x轴方向的值的参照(Animation.ABSOLUTE,
*            Animation.RELATIVE_TO_SELF,or Animation.RELATIVE_TO_PARENT);
* @param fromXValue
*            第二个参数是第一个参数类型的起始值;
* @param toXType
*            第三个参数与第四个参数是x轴方向的终点参照与对应值
* @param toXValue
*            结束位置的值
* @param fromYType
* @param fromYValue
* @param toYType
* @param toYValue
* @param durationMillis
* @return
* @throws
*/
public static Animation getTranslateAnimations(int fromXType,
float fromXValue, int toXType, float toXValue, int fromYType,
float fromYValue, int toYType, float toYValue, long durationMillis) {
TranslateAnimation translate = new TranslateAnimation(fromXType,
fromXValue, toXType, toXValue, fromYType, fromYValue, toYType,
toYValue);
translate.setDuration(durationMillis);
translate.setFillAfter(false);
return translate;
}

/**
* @Title: getAnimationSet
* @Description: 组合动画
* @return
* @throws
*/
public static AnimationSet getAnimationSet() {
// 顶一个一个set
AnimationSet animationSet = new AnimationSet(false);
ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
sa.setDuration(2000);
sa.setRepeatCount(2);
sa.setRepeatMode(Animation.REVERSE);

RotateAnimation ra = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF,
1.0f);
ra.setDuration(2000);
ra.setRepeatCount(2);
ra.setRepeatMode(Animation.REVERSE);

TranslateAnimation ta = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 1.0f);

ta.setDuration(2000);
ta.setRepeatCount(2);
ta.setRepeatMode(Animation.REVERSE);
// 将定义好的动画直接加入到set中
animationSet.addAnimation(sa);
animationSet.addAnimation(ra);
animationSet.addAnimation(ta);
return animationSet;
}

}


二、在XML文件中自定义动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<!--
%:相对于view自身位置移动,相当于Animation.RELATIVE_TO_SELF
%p:相对于父元素,参考的是父元素,相当于Animation.RELATIVE_TO_PARENT
什么都不写相当于Animation.ABSOLUTE

其中interpolator是一个函数计算过程,是动画播放过程中的变化率
Android提供的几个定义好的类直接使用,有兴趣的朋友也可以自己去自定义变化率
AccelerateDecelerateInterpolator        在动画开始与介绍的地方速率改变比较慢,在中间的时侯加速
AccelerateInterpolator        在动画开始的地方速率改变比较慢,然后开始加速
CycleInterpolator        动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator        在动画开始的地方速率改变比较慢,然后开始减速
LinearInterpolator        在动画的以均匀的速率改变

-->

<scale
android:duration="200"
android:fillAfter="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="restart"
android:toXScale="1.0"
android:toYScale="1.0" />

<alpha
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />

<translate
android:fillAfter="true"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:repeatCount="2"
android:repeatMode="restart"
android:toXDelta="100%"
android:toYDelta="100%" />

<rotate
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="restart"
android:toDegrees="100" />

</set>


调用XML编写的动画只需要写Animation animation = AnimationUtils.loadAnimation(this,R.anim.xxx);即可

三、Anctivity切换动画:

对于Activity切换动画,我们只需要在startActivity之后,加上一句即可:

Intent intent=new Intent(PathButtonActivity.this,MainActivity.class);

startActivity(intent);

//第一个参数为启动时动画效果,第二个参数为退出时动画效果

overridePendingTransition(R.anim.fade, R.anim.hold);

四、Fragment切换动画

在使用fragment切换动画的时候要特别注意,如果你的fragment不是V4包的fragment,那么使用切换的动画资源必须放置在res\animator的目录下,且根标签是<set><objectAnimator><valueAnimator>之一,至于为什么,有兴趣的朋友可以去研究一下Property Animation和View Animation的区别。因为我们常用的fragment肯定是包含V4包的,兼容性比较好,所以,我们只讲在anim文件夹下的动画使用。看代码:

FragmentTransaction fragmentTransaction = mFragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(
R.anim.push_left_in,
R.anim.push_left_out,
R.anim.push_left_in,
R.anim.push_left_out);

fragmentTransaction.add(R.id.container, mTextFragmentOne);


在切换fragment使用动画的时候,必须在add或者replace之前调用setCustomAnimations()方法。

五、Dialog、PopupWindow以及WindowManager弹窗动画效果

这三者的实现动画效果方式,其实是差不多的,都需要先定义一个风格style,看代码:

<style name="freedom_anim_style">
<item name="android:windowEnterAnimation">@anim/popshow_anim</item> <!-- 指定显示的动画xml -->
<item name="android:windowExitAnimation">@anim/pophidden_anim</item> <!-- 指定消失的动画xml -->
</style>


有了这个风格style之后,就方便很多了

1、Dialog实现弹出动画:

AlertDialog.Builder b = new Builder(this);
b.create().getWindow().setWindowAnimations(R.style.freedom_anim_style);


2、PopupWindow实现弹出动画:

PopupWindow p = new PopupWindow();
p.setAnimationStyle(R.style.freedom_anim_style);


3、WindowManger添加窗体实现弹出动画:(这个稍微多几步,但是其实原理和之前两个弹窗的底层是一样的)我们以添加一个view为例子

view = View.inflate(context, R.layout.freedom, null);

WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, // 没有边界
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.TOP;
// 重要 这就是添加动画的地方
lp.windowAnimations = R.style.freedom_anim_style;
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(view, lp);


到此Android开发中常用的动画以及使用场景方式已经讲解完毕,希望能够帮助到看到此篇文章的人。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐