手游SDK-动画
一、Dialog切换动画。
1、动画基础
Android 中的动画可以分为逐帧动画、补间动画、属性动画三类。
1)、逐帧动画
逐帧动画就是依次播放图片,每一帧都是一张图片。利用人眼视觉暂留的原理,实现动画。就如同平时的电影、动漫一样。
逐帧动画通常是采用XML资源进行定义,在 <animation-list …/> 标签下使用 <item …/> 子元素标签定义动画的全部帧,并指定各帧的持续时间。
在res/drawable下新建frame_animation.xml,并放入素材图片。
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/animation01" android:duration="50"/>
<item android:drawable="@drawable/animation02" android:duration="50"/>
</animation-list>
其中android:oneshot控制动画是否循环播放。如果为true,动画将不会循环播放,否则该动画将会循环播放。
duration 为时间间隔,单位为毫秒。
将frame_animation.xml转换成AnimationDrawable对象。
frameAnim=(AnimationDrawable) getResources().getDrawable(R.drawable.frame_animation);
view.setBackgroundDrawable(frameAnim); //把动画设置为ImageView的背景
如果利用Java来实现
首先要创建AnimationDrawable对象
animationDrawable = new AnimationDrawable();
for (int i = 1; i < 9; i ++ ){
int id = getResources().getIdentifier("animation0" + i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
animationDrawable.addFrame(drawable, 50);
}
animationDrawable.setOneShot(true);
view.setBackgroundDrawable(animationDrawable);
2)、补间动画
补间动画就是指定动画开始、结束的关键帧。而动画变化的中间帧由系统计算补齐。
补件动画共有四种类型:TranslateAnimation-位移动画、ScaleAnimation-缩放动画、RotateAnimation-旋转动画、AlphaAnimation-透明度改变动画。还有一种AnimationSet-补间动画四种动画组合。
补间动画需要在res/anim/文件夹下定义动画资源。
alpha_anim.xml:透明度改变动画
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="0.0" />
duration:持续时间,单位为毫秒。
fromAlpha 和 toAlpha:透明度
interpolator:插值器,主要作用是控制动画的变化速率,可以通过 @android:anim 来选择不同的插值器。
scale_anim.xml:缩放动画
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"/>
pivot:参考点,值可以是float或者是百分比数值。
以 pivotX 为例,说明其取不同的值的含义:
10:距离动画所在view自身左边缘10像素
10% :距离动画所在view自身左边缘 的距离是整个view宽度的10%
10%p:距离动画所在view父控件左边缘的距离是整个view宽度的10%
translate_anim.xml:位移动画
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegree="0"
android:toDegree="1800"
android:pivotX = "50%"
android:pivotY="50%"
android:duration = "3000"
/>
rotate_anim.xml:旋转动画
<?xml version="1.0" encoding="utf-8"?>
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="50%"
android:pivotY="50%" />
最后使用loadAnimation将XML布局解析成Animation类。然后在控件中startAnimation,即可开启动画。
Animation animation = AnimationUtils.loadAnimation(this, R.xx.xxx);
// 开启动画
view.startAnimation(animation);
如果利用Java来实现
位移动画:
Animation translateAnimation = new TranslateAnimation(0,500,0,500);
translateAnimation.setDuration(3000);
mButton.startAnimation(translateAnimation);
缩放动画:
Animation scaleAnimation= new ScaleAnimation(0,2,0,2,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
scaleAnimation.setDuration(3000);
mButton.startAnimation(scaleAnimation);
旋转动画:
Animation rotateAnimation = new RotateAnimation(0,270,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(3000);
mButton.startAnimation(rotateAnimation);
透明度改变动画:
Animation alphaAnimation = new AlphaAnimation(1,0);
alphaAnimation.setDuration(3000);
mButton.startAnimation(alphaAnimation);
3)、属性动画
属性动画,通过动态的改变对象的属性从而达到动画效果。
补间动画只是改变了View的显示效果而已,并不会真正的改变View的属性。而属性动画可以改变View的显示效果和属性。举个例子:例如屏幕左上角有一个Button按钮,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已,而属性动画则不会。
2、登陆界面的切换效果代码
切换效果为左右切换,点击后退时界面从左到右切入,下一步(注册,忘记密码等)时从右到左切入界面。
示例代码:
//viewCur为现在的view,viewNext为将要展示的view,isBack为是否后退
protected void switchViewAnim(final View viewCur, final View viewNext, boolean isBack, boolean hasAnim) {
if (viewNext == null && viewCur == null) { //如果view全为null则返回
return;
}
if(LoginDialog == null){
return;
}
if (viewNext != null && viewCur == null) { //登录界面最后的界面,无需动画
if (!hasAddView(viewNext)) {
LoginDialog.addView(viewNext);
}
viewNext.setVisibility(View.VISIBLE);
LoginDialog.post(new Thread() {
@Override
public void run() {
ViewBase viewBase = (ViewBase) viewNext.getTag();
requestFocus(viewBase);
}
});
return;
}
if (viewNext == null && viewCur != null) { //登录界面的第一个界面,也无需动画
if (!hasAddView(viewCur)) {
LoginDialog.addView(viewCur);
}
viewCur.setVisibility(View.VISIBLE);
LoginDialog.post(new Thread() {
@Override
public void run() {
ViewBase viewBase = (ViewBase) viewCur.getTag();
requestFocus(viewBase);
}
});
return;
}
isAniming = true;
int params[] = { 0, -1, 1, 0 }; //前进(动画)
if (isBack) {
params = new int[] { 0, 1, -1, 0 }; //后退(动画)
}
int duration = 250;//持续时间
//设置动画效果
TranslateAnimation taCur = new TranslateAnimation(Animation.RELATIVE_TO_SELF, params[0],
Animation.RELATIVE_TO_SELF, params[1], Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
TranslateAnimation taNext = new TranslateAnimation(Animation.RELATIVE_TO_SELF, params[2],
Animation.RELATIVE_TO_SELF, params[3], Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
taCur.setDuration(duration);
taCur.setRepeatCount(0);
taCur.setInterpolator(new LinearInterpolator());
taNext.setDuration(duration);
taNext.setRepeatCount(0);
taNext.setInterpolator(new LinearInterpolator());
taCur.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if(LoginDialog == null){
return;
}
LoginManager.getInstance().getLoginLayoutDialog().post(new Thread() {
@Override
public void run() {
viewCur.setVisibility(View.GONE);
ViewBase viewBase = (ViewBase) viewNext.getTag();
viewBase.onAnimEnd();
requestFocus(viewBase);
}
});
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
if (!hasAddView(viewCur)) {
LoginDialog.addView(viewCur);
}
if (!hasAddView(viewNext)) {
LoginDialog.addView(viewNext);
}
viewCur.clearAnimation();
viewNext.clearAnimation();
if (hasAnim) {
viewCur.startAnimation(taCur);
viewNext.startAnimation(taNext);
} else {
isAniming = false;
}
viewCur.setVisibility(hasAnim ? View.VISIBLE : View.GONE);
viewNext.setVisibility(View.VISIBLE);
}
主要使用位移动画TranslateAnimation来实现动画效果,利用参数isBack来确定使用何种动画。因为有back返回键,所以需要记录view的跳转,方便按返回时,返回上一个界面。
二、加载动画等
如果是一般APP,可以使用AVLoadingIndicatorView等第三方库,AVLoadingIndicatorView的使用还是比较简单的,而且加载动画的数量和效果也基本够用。但是我们这个是SDK,尽量不要引入第三方库,以避免和其他SDK或者APP起冲突。
如果对加载动画没特殊要求的,可以使用Android自带的ProgressBar进度条控件。
ProgressBar默认为圆形进度,循环转圈,不显示具体的进度值。
setVisibility:控制显示or隐藏
setIndeterminateDrawable:设置图片
ProgressBar也可以通过设置style="?android:attr/progressBarStyleHorizontal"变为横向进度条。
setProgress:可以设置具体的进度
如果不满足ProgressBar的效果,那可以通过自定义View来创建对应的加载动画。
自定义view的时候需要继承view并重写父类的onMeasure()、onLayout()、onDraw()三个方法。
measure:测量。系统会先根据xml布局文件和代码中对控件属性的设置,来获取或者计算出每个View和ViewGrop的尺寸,并将这些尺寸保存下来。
layout:布局。根据测量出的结果以及对应的参数,来确定每一个控件应该显示的位置。
draw:绘制。确定好位置后,就将这些控件绘制到屏幕上。
上一篇: 手游SDK-登录界面
下一篇: 手游SDK-支付
上一篇: egret加载资源改成进度条
下一篇: 【flask】session的操作