【Android开发日记】之基础篇(二)——Android的动画效果
什么是动画,动画的本质是通过连续不断地显示若干图像来产生“动”起来的效果。比如说一个移动的动画,就是在一定的时间段内,以恰当的速率(起码要12帧/秒以上,才会让人产生动起来的错觉)每隔若干时间在屏幕上更新一次位置。游戏中的动画效果也是由此而来。同样还有其他属性变更所引起的动画效果,从数学的角度来看,包括:(1)平移(2)旋转(3)缩放(4)透明度。当然这些属性可以组合起来使用,来达到更绚丽的画面。但是不论什么样的组合方式,我们都可以统一用Matirx运算来实现,从技术实现的角度来讲,Matrix是动画的核心,2D不用说,3D更是依赖矩阵(Matrix)的运算。当然,今天只是讲讲怎么实现动画效果,不会涉及这些基础知识~~
一、Tween Animation(补间动画)
补间动画可以实现View组件的移动、放大、缩小以及渐变等效果。也是我们使用动画效果时最常用的动画了。
一共有四种动画,分别为
AlphaAnimation | 渐变透明度动画效果 |
ScaleAnimation | 渐变尺寸伸缩动画效果 |
TranslateAnimation | 画面转换位置移动动画效果 |
RotateAnimation | 画面转移旋转动画效果 |
而设置动画也有两种方式,一种是在代码中设置,另一种就是在xml文件中配置。
- 设置alpha的动画
public Animation AlphaAnimation(){
Animation myAnimation_Alpha;
//透明度从0到1
myAnimation_Alpha = new AlphaAnimation(0,1);
//设置时间持续时间为 2000毫秒
myAnimation_Alpha.setDuration(2000);
return myAnimation_Alpha;
}很简单,新建一个AlphaAnimation的类,里面放着要变化的起始参数和结束参数,然后程序就会自动演化出过场的动画。最后在要动画的view上设置
myAnimation = AlphaAnimation();
av.startAnimation(myAnimation);//av是一个imageview - 设置rotate的动画
public Animation RotateAnimation(){
Animation myAnimation_Rotate;
//第一个参数fromDegrees为动画起始时的旋转角度
//第二个参数toDegrees为动画旋转到的角度
//第三个参数pivotXType为动画在X轴相对于物件位置类型
//第四个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第五个参数pivotXType为动画在Y轴相对于物件位置类型
//第六个参数pivotYValue为动画相对于物件的Y坐标的开始位置
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
//动画插入器,可以自己定义动画的速度
//加速-减速 动画插入器
myAnimation_Rotate.setInterpolator(this,android.R.anim.accelerate_decelerate_interpolator);
myAnimation_Rotate.setDuration(2000);
return myAnimation_Rotate;
}里面有一个动画插入器的概念,这是控制动画过程速度的一个方法,比如上面代码中的accelerate_decelerate_interpolator就是要求动画先加速运行,在减速运行
- 设置Translate的动画
public Animation TranslateAnimation(){
//TranslateAnimation(float fromXDelta, float toXDelta,
//float fromYDelta, float toYDelta)
//第一个参数fromXDelta为动画起始时 X坐标上的移动位置
//第二个参数toXDelta为动画结束时 X坐标上的移动位置
//第三个参数fromYDelta为动画起始时Y坐标上的移动位置
//第四个参数toYDelta为动画结束时Y坐标上的移动位置
Animation myAnimation_Translate;
myAnimation_Translate=new TranslateAnimation(0.0f, -80.0f, 0.0f, 300.0f);
myAnimation_Translate.setDuration(2000);
myAnimation_Translate.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) { } @Override
public void onAnimationEnd(Animation animation) {
av.setTranslationX(av.getTranslationX()-80f);
av.setTranslationY(av.getTranslationY()+300f);
} @Override
public void onAnimationRepeat(Animation animation) { }
});
return myAnimation_Translate;
}位移动画的参数很简单明了,就是对x,y位置的起始结束的地方做标记然后进行动画。view运行完动画后会恢复原来的状态
这里提到了一个监听器的概念,如上面的方法所示,可以对动画的开始时刻,结束时刻以及重复时刻进行监听,然后调用自己写入的方法。 - 设置Scale动画
public Animation ScaleAnimation(){
Animation myAnimation_Scale;
//第一个参数fromX为动画起始时 X坐标上的伸缩尺寸
//第二个参数toX为动画结束时 X坐标上的伸缩尺寸
//第三个参数fromY为动画起始时Y坐标上的伸缩尺寸
//第四个参数toY为动画结束时Y坐标上的伸缩尺寸
/*说明:
以上四种属性值
0.0表示收缩到没有
1.0表示正常无伸缩
值小于1.0表示收缩
值大于1.0表示放大
*/
//第五个参数pivotXType为动画在X轴相对于物件位置类型
//第六个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第七个参数pivotXType为动画在Y轴相对于物件位置类型
//第八个参数pivotYValue为动画相对于物件的Y坐标的开始位置
/*myAnimation_Scale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
myAnimation_Scale.setDuration(2000);*/ //使用xml读取动画
myAnimation_Scale = AnimationUtils.loadAnimation(this,R.anim.scale);
return myAnimation_Scale;
}这里我们使用读取anim文件夹下的xml文件来设置动画(若res文件夹下没有anim文件夹要自己创建)
xml内部内容如下:<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator=
"@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
</set>
<!-- 尺寸伸缩动画效果 scale
属性:interpolator 指定一个动画的插入器
在我试验过程中,使用android.res.anim中的资源时候发现
有三种动画插入器:
accelerate_decelerate_interpolator 加速-减速 动画插入器
accelerate_interpolator 加速-动画插入器
decelerate_interpolator 减速- 动画插入器
其他的属于特定的动画效果
浮点型值: fromXScale 属性为动画起始时 X坐标上的伸缩尺寸
toXScale 属性为动画结束时 X坐标上的伸缩尺寸 fromYScale 属性为动画起始时Y坐标上的伸缩尺寸
toYScale 属性为动画结束时Y坐标上的伸缩尺寸 说明:
以上四种属性值 0.0表示收缩到没有
1.0表示正常无伸缩
值小于1.0表示收缩
值大于1.0表示放大 pivotX 属性为动画相对于物件的X坐标的开始位置
pivotY 属性为动画相对于物件的Y坐标的开始位置 说明:
以上两个属性值 从0%-100%中取值
50%为物件的X或Y方向坐标上的中点位置 长整型值:
duration 属性为动画持续时间
说明: 时间以毫秒为单位 布尔型值:
fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用
-->scale的参数可能有点多,其实也就是比Translate的动画多了设置中心点的参数,其他跟Translate类似,只不过scale是对x,y进行缩放而不是位移
- AnimationsSet,动画集合
private AnimationSet mySet = new AnimationSet(true);
public void AllAnimation(){
mySet.addAnimation(AlphaAnimation());
mySet.addAnimation(RotateAnimation());
mySet.addAnimation(TranslateAnimation());
mySet.addAnimation(ScaleAnimation());
mySet.setDuration(3000);
av.startAnimation(mySet);
}动画集合可以将多个动画放到一个集合中,然后一起进行播放。(AnimationSet也是继承自Animation类,所以其它的属性跟单个动画差不多)
- 完整代码
public class MyActivity extends Activity implements View.OnClickListener { private ImageView av;
private Button alpha,rotate,translate,scale;
private AnimationSet mySet;
private Button allAnimation,back; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mySet = new AnimationSet(true);
av = (ImageView)findViewById(R.id.imageView2);
alpha = (Button)findViewById(R.id.alpha);
alpha.setOnClickListener(this);
rotate = (Button)findViewById(R.id.rotate);
rotate.setOnClickListener(this);
translate = (Button)findViewById(R.id.translate);
translate.setOnClickListener(this);
scale = (Button)findViewById(R.id.scale);
scale.setOnClickListener(this);
allAnimation = (Button)findViewById(R.id.all);
allAnimation.setOnClickListener(this);
back = (Button)findViewById(R.id.back);
back.setOnClickListener(this);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} @Override
public void onClick(View v) {
Animation myAnimation = null;
switch(v.getId()){
case R.id.alpha:
myAnimation = AlphaAnimation();
av.startAnimation(myAnimation);//av是一个imageview
break;
case R.id.rotate:
myAnimation = RotateAnimation();
av.startAnimation(myAnimation);
break;
case R.id.translate:
myAnimation = TranslateAnimation();
av.startAnimation(myAnimation);
break;
case R.id.scale:
myAnimation = ScaleAnimation();
av.startAnimation(myAnimation);
break;
case R.id.all:
AllAnimation();
break;
case R.id.back:
this.finish();
break;
}
} public Animation AlphaAnimation(){
Animation myAnimation_Alpha;
//透明度从0到1
myAnimation_Alpha = new AlphaAnimation(0,1);
//设置时间持续时间为 2000毫秒
myAnimation_Alpha.setDuration(2000);
return myAnimation_Alpha;
} public Animation RotateAnimation(){
Animation myAnimation_Rotate;
//第一个参数fromDegrees为动画起始时的旋转角度
//第二个参数toDegrees为动画旋转到的角度
//第三个参数pivotXType为动画在X轴相对于物件位置类型
//第四个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第五个参数pivotXType为动画在Y轴相对于物件位置类型
//第六个参数pivotYValue为动画相对于物件的Y坐标的开始位置
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
//动画插入器,可以自己定义动画的速度
//加速-减速 动画插入器
myAnimation_Rotate.setInterpolator(this,android.R.anim.accelerate_decelerate_interpolator);
myAnimation_Rotate.setDuration(2000);
return myAnimation_Rotate;
} public Animation TranslateAnimation(){
//TranslateAnimation(float fromXDelta, float toXDelta,
//float fromYDelta, float toYDelta)
//第一个参数fromXDelta为动画起始时 X坐标上的移动位置
//第二个参数toXDelta为动画结束时 X坐标上的移动位置
//第三个参数fromYDelta为动画起始时Y坐标上的移动位置
//第四个参数toYDelta为动画结束时Y坐标上的移动位置
Animation myAnimation_Translate;
myAnimation_Translate=new TranslateAnimation(0.0f, -80.0f, 0.0f, 300.0f);
myAnimation_Translate.setDuration(2000);
myAnimation_Translate.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) { } @Override
public void onAnimationEnd(Animation animation) {
av.setTranslationX(av.getTranslationX()-80f);
av.setTranslationY(av.getTranslationY()+300f);
} @Override
public void onAnimationRepeat(Animation animation) { }
});
return myAnimation_Translate;
} public Animation ScaleAnimation(){
Animation myAnimation_Scale;
//第一个参数fromX为动画起始时 X坐标上的伸缩尺寸
//第二个参数toX为动画结束时 X坐标上的伸缩尺寸
//第三个参数fromY为动画起始时Y坐标上的伸缩尺寸
//第四个参数toY为动画结束时Y坐标上的伸缩尺寸
/*说明:
以上四种属性值
0.0表示收缩到没有
1.0表示正常无伸缩
值小于1.0表示收缩
值大于1.0表示放大
*/
//第五个参数pivotXType为动画在X轴相对于物件位置类型
//第六个参数pivotXValue为动画相对于物件的X坐标的开始位置
//第七个参数pivotXType为动画在Y轴相对于物件位置类型
//第八个参数pivotYValue为动画相对于物件的Y坐标的开始位置
/*myAnimation_Scale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
myAnimation_Scale.setDuration(2000);*/ //使用xml读取动画
myAnimation_Scale = AnimationUtils.loadAnimation(this,R.anim.scale);
return myAnimation_Scale;
} public void AllAnimation(){
mySet.addAnimation(AlphaAnimation());
mySet.addAnimation(RotateAnimation());
mySet.addAnimation(TranslateAnimation());
mySet.addAnimation(ScaleAnimation());
mySet.setDuration(3000);
av.startAnimation(mySet);
} }
二、Frame Animation(逐帧动画)
所谓的逐帧动画就是平常我们观看的视频一样,都是一帧一帧的快速播放图片来欺骗观众的眼球以达到动起来的错觉。
- 逐帧动画可以使用xml文件来进行设置
<?xml version="1.0" encoding="utf-8"?>
<!-- animation-list是一组图片的数组,用来逐帧显示 -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" ><!-- oneshot表示是否只循环一遍 -->
<item android:drawable="@drawable/p0" android:duration="500" />
<item android:drawable="@drawable/p1" android:duration="500" />
<item android:drawable="@drawable/p2" android:duration="500" />
<item android:drawable="@drawable/p3" android:duration="500" />
<item android:drawable="@drawable/p4" android:duration="500" />
<item android:drawable="@drawable/p5" android:duration="500" />
</animation-list>上面每个item就是一张图片,这个xml文件要放在drawable文件夹中。
在代码中调用iv.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable anim = (AnimationDrawable) iv.getBackground();
anim.start();iv是一个ImageView控件,设置背景图像后,就可以开始动画。
- 直接用代码生成逐帧动画
//完全编码实现的动画效果
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
//根据资源名称和目录获取R.java中对应的资源ID
int id = getResources().getIdentifier("p" + i, "drawable", getPackageName());
//根据资源ID获取到Drawable对象
Drawable drawable = getResources().getDrawable(id);
//将此帧添加到AnimationDrawable中
anim.addFrame(drawable, 500);
}
anim.setOneShot(false); //设置为loop
//api15以前
iv.setBackgroundDrawable(anim); //将动画设置为ImageView背景
//api16以后
//iv.setBackground(anim);
anim.start(); //开始动画 - 全部代码
package com.cpacm.demo.testrep; import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; import com.cpacm.demo.testrep.R; public class FrameAnimationActivity extends Activity implements View.OnClickListener{ private ImageView iv;
private Button b1,b2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_animation);
iv = (ImageView)findViewById(R.id.imageView);
b1 = (Button)findViewById(R.id.start);
b1.setOnClickListener(this);
b2 = (Button)findViewById(R.id.end);
b2.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch(v.getId()){
case R.id.start:
iv.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable anim = (AnimationDrawable) iv.getBackground();
anim.start();
//runFrame();
break;
case R.id.end:
AnimationDrawable anim2 = (AnimationDrawable) iv.getBackground();
if (anim2.isRunning()) { //如果正在运行,就停止
anim2.stop();
}
break;
}
} public void runFrame() {
//完全编码实现的动画效果
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
//根据资源名称和目录获取R.java中对应的资源ID
int id = getResources().getIdentifier("p" + i, "drawable", getPackageName());
//根据资源ID获取到Drawable对象
Drawable drawable = getResources().getDrawable(id);
//将此帧添加到AnimationDrawable中
anim.addFrame(drawable, 500);
}
anim.setOneShot(false); //设置为loop
//api15以前
iv.setBackgroundDrawable(anim); //将动画设置为ImageView背景
//api16以后
//iv.setBackground(anim);
anim.start(); //开始动画
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.frame_animation, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} } - 效果截图
三、Activity Animation(切换动画)
Activity之间切换也是有动画的,我们可以直接拿系统默认的动画,也可以使用自定义的动画
Intent intent = new Intent();
intent.setClass(mainActivity.this,TweenAnimationActivity.class);
startActivity(intent);
overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);//系统自带的切换动画
放在intent跳转antivity的后面。
自带的动画这样写
//如果这个地方想用自己的,可以调用anim文件夹下的xml文件,如下:
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
xml文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" > <translate
android:duration="300"
android:fromYDelta="100%p"
android:toYDelta="0" /> <alpha
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" /> </set>
push_left_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- push_up_out 上下滑入式 -->
<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="-100%p" /> <alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.0" /> </set>
push_left_out
overridePendingTransition(arg1,arg2);
里面的两个参数分别是进入的activity动画和退出的activity动画。
四、ObjectAnimator(属性动画)
Animator框架是Android 4.0中新添加的一个动画框架,和之前的Animation框架相比,Animator可以进行更多和更精细化的动画控制,而且比之前更简单和更高效。在4.0源码中随处都可以看到Animator的使用。
Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是一个整个View动画,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU资源。
在Animator框架中使用最多的是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值,多个ObjectAnimator组合到AnimatorSet形成一个动画。而且ObjectAnimator能够自动驱动,可以调用setFrameDelay(long frameDelay)设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,而在不影响动画效果的前提下减少CPU资源消耗。
//第一个参数是属性,即要变化的属性,下面是变化的值,可以放置多个数值
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat(View.TRANSLATION_X,100);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 1f);
PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 730);
PropertyValuesHolder pvhsX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1,2,1);
PropertyValuesHolder pvhsY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1,2,1);
PropertyValuesHolder pvhA = PropertyValuesHolder.ofFloat(View.ALPHA, 1);
final ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(iv, pvhX, pvhY, pvhR, pvhsX, pvhsY, pvhA);
animation.setDuration(2000);
animation.setInterpolator(new OvershootInterpolator(0.9f));
animation.start();
主要是ObjectAnimator,其ObjectAnimator.ofPropertyValuesHolder(view,PropertyValuesHolder...)的方法是给view设置一系列的动画,与AnimationSet类似。
详细的用法可以 参考文章(5)ApiDemos解析
完整代码:
package com.cpacm.demo.testrep; import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import android.widget.Button;
import android.widget.ImageView; public class ObjectAnimatorActivity extends Activity implements View.OnClickListener{ private ImageView iv;
private Button b1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_object_animator);
iv = (ImageView)findViewById(R.id.imageView2);
b1 = (Button)findViewById(R.id.button);
b1.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button:
//第一个参数是属性,即要变化的属性,下面是变化的值,可以防止多个数值
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat(View.TRANSLATION_X,100);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 1f);
PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, 730);
PropertyValuesHolder pvhsX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1,2,1);
PropertyValuesHolder pvhsY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1,2,1);
PropertyValuesHolder pvhA = PropertyValuesHolder.ofFloat(View.ALPHA, 1);
final ObjectAnimator animation = ObjectAnimator.ofPropertyValuesHolder(iv, pvhX, pvhY, pvhR, pvhsX, pvhsY, pvhA);
animation.setDuration(2000);
animation.setInterpolator(new OvershootInterpolator(0.9f));
animation.start();
break;
} } @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.object_animator, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} }
效果:
五、结束语
动画在android的UI设计中总是占着一席之地,动画往往会给用户带来一种生动的感觉,所以学习好动画的设计是很重要的。这篇文章列举的动画种类可能不全,我也是根据自己用过的动画做了个总结而已,如果还有其他的动画API欢迎大家补充。那么大家下次再见~
参考文章:(1) Android动画效果 第九章 http://book.51cto.com/art/201204/328247.htm
(2)详解Android动画之Frame Animation http://blog.csdn.net/liuhe688/article/details/6657776
(3)Android Activity之间动画完整版详解 http://mzh3344258.blog.51cto.com/1823534/807337
(5)ApiDemos解析:多属性动画 http://www.cnblogs.com/mengdd/archive/2013/09/06/3305698.html
Demo地址:https://github.com/cpacm/android_learn/tree/master/AnimationDemo
========================================
作者:cpacm
地址:http://www.cnblogs.com/cpacm/p/4067283.html
【Android开发日记】之基础篇(二)——Android的动画效果的更多相关文章
- 【Android开发日记】第一个任务Android Service!Service靴+重力感应器+弹出窗口+保持执行
前言: 近期在写一个小程序,需求是手机摇一摇就弹窗出来.第一次使用了Service,学习了两天,实现了Service弹窗,开机启动,Service启动和销毁,Service保持一直执行. 满足了自己的 ...
- 【Android开发日记】之入门篇(十二)——Android组件间的数据传输
组件我们有了,那么我们缺少一个组件之间传递信息的渠道.利用Intent做载体,这是一个王道的做法.还有呢,可以利用文件系统来做数据共享.也可以使用Application设置全局数据,利用组件来进行控制 ...
- 【Android开发日记】之入门篇(七)——Android数据存储(上)
在讲解Android的数据源组件——ContentProvider之前我觉得很有必要先弄清楚Android的数据结构. 数据和程序是应用构成的两个核心要素,数据存储永远是应用开发中最重要的主题之一,也 ...
- 【Android开发日记】之入门篇(九)——Android四大组件之ContentProvider
数据源组件ContentProvider与其他组件不同,数据源组件并不包括特定的功能逻辑.它只是负责为应用提供数据访问的接口.Android内置的许多数据都是使用ContentProvider形式,供 ...
- 【Android开发日记】之入门篇(十四)——Button控件+自定义Button控件
好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把 ...
- 【Android开发日记】之入门篇(十三)——Android的控件解析
Android的控件都派生自android.view.View类,在android.widget包中定义了大量的系统控件供开发者使用,开发者也可以从View类及其子类中,派生出自定义的控件. 一.An ...
- 【Android开发日记】之入门篇(十一)——Android的Intent机制
继续我们的Android之路吧.今天我要介绍的是Android的Intent. 对于基于组件的应用开发而言,不仅需要构造和寻找符合需求的组件,更重要的是要将组件有机的连接起来,互联互通交换信息,才能够 ...
- 【Android开发日记】之入门篇(一)——开发环境的搭建
写给自己的话:至此,大学的时光已经剩下一年的时光,下一年等毕业设计结束后就算是正式地踏入社会.自己学android也不过几个月的时间,为了更好管理文档,写点东西记录下自己曾经做过的点点滴滴是一个不错的 ...
- 【Android开发日记】之入门篇(八)——Android数据存储(下)
废话不多说了,紧接着来讲数据库的操作吧.Come On! 提到数据存储问题,数据库是不得不提的.数据库是用来存储关系型数据的不二利器.Android为开发者提供了强大的数据库支持,可以用来轻松地构造基 ...
- 【Android开发日记】之入门篇(五)——Android四大组件之Service
这几天忙着驾校考试,连电脑都碰不到了,今天总算告一段落了~~Service作为Android的服务组件,默默地在后台为整个程序服务,辅助应用与系统中的其他组件或系统服务进行沟通.它跟Activity的 ...
随机推荐
- [CF551E]GukiZ and GukiZiana
题目大意:一个长度为$n(n\leqslant5\times10^5)$的数组,有两个操作: $1\;l\;r\;x:$把区间$[l,r]$加上$x$ $2\;x:$询问$x$第一次出现和最后一次出现 ...
- 周记【距gdoi:133天】
蔡大神坚持每天写日记记录他所剩的oi生涯. 可是我呢?自从搞完数据结构后都不知道在干什么,整天在傻叉.也许是给自己压力太大了,或许是真的自己在迷茫以及犹豫,更或者自己真的是想太多不想写题,觉得烦了,没 ...
- harbor1.4.0高可用部署
一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Parent 构造函数成为 Children 的方法,然 ...
- BZOJ1059:[ZJOI2007]矩阵游戏——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1059 https://www.luogu.org/problemnew/show/P1129 小Q是 ...
- 阿里云配置redis
一.redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sor ...
- C++之内部类与外部类(嵌套类)及友元
转载于:http://www.cnblogs.com/qzhforthelife/p/3226885.html 先上代码: class Outer { public: Outer(){m_outerI ...
- Leetcode 557. 反转字符串中的单词 III
1.题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode contest" ...
- Leetcode 200. 岛屿的个数(扩展)
1.题目描述 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 ...
- 名人问题/名流问题/Celebrity
问题描述:名人问题一个名人就是指这样一个人:所有其他人都认识他,并且他不认识任何其他人.现在有一个N个人的集合,以及他们之间的认识关系.求一个算法找出其中的名人(如果有的话)或者判断出没有名人(如果没 ...
- js ejs for语句的第二种遍历用法
var A = {a:1,b:2,c:3,d:"hello world"}; for(var k in A) { console.log(k,A[k]); var h = new ...