安卓动画系列之属性动画实现跳起落下圆圈运动
最近看了淘宝手机端的有些页面是类似下面这个小球的加载效果。后来了解了下,淘宝是直接一个gif图片实现效果的,这当然是最简单的方法。为了加深了解属性动画,这次就做个类似的效果。这依旧由几个简单的属性动画组合在一起,所有动画都在代码里实现了。看注释就好。
上个效果图:
实现代码:
小球圆圈的XML文件 drawable_dot.xml:
<?xml version="1.0" encoding="utf-8" ?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <size android:height="40dp" android:width="40dp" /> <solid android:color="#D2691E" /> </shape>
Activity的布局文件,就是一个ImageView:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imv_tb_dot1" android:layout_width="20dp" android:layout_height="20dp" android:layout_centerInParent="true" android:src="@drawable/drawable_dot" /> </RelativeLayout>
主类MainActivity:
package com.alextam.circlemoveball; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.media.Image; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; /** * @author Alex Tam */ public class MainActivity extends ActionBarActivity { private ImageView imv1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imv1= (ImageView)findViewById(R.id.imv_tb_dot1); setCircleMoveBall(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, 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(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * 设置小球动画 */ private void setCircleMoveBall() { ValueAnimator animatorMove = ValueAnimator.ofInt(0,200); animatorMove.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { imv1.setTranslationX((Integer) animation.getAnimatedValue()); } }); animatorMove.setDuration(1000); ValueAnimator animatorMoveScale = ValueAnimator.ofFloat(0.0f,100.0f); animatorMoveScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (Float)animation.getAnimatedValue(); //将动画的小球运动分解为2部,当0.0f - 50.0f小球变大,后面一半50.0f-100.0f小球从大恢复正常 //这里效果看起来是小球从平面向屏幕弹起的样子 if(value<= 50.0f) { imv1.setScaleX(1.0f + value/50); imv1.setScaleY(1.0f + value/50); } else { imv1.setScaleX(1.0f - (value - 100.0f)/50); imv1.setScaleY(1.0f - (value - 100.0f)/50); } } }); animatorMoveScale.setDuration(1000); ValueAnimator animatorBackMove = ValueAnimator.ofInt(200,0); animatorBackMove.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { imv1.setTranslationX((Integer) animation.getAnimatedValue()); } }); animatorBackMove.setDuration(2000); ValueAnimator animatorBackScale = ValueAnimator.ofFloat(0.0f,-100.0f); animatorBackScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (Float)animation.getAnimatedValue(); float vluA,vluB; //同样是将小球分解两步,效果就是动画中的往后变小,透明度逐渐变低,然后恢复正常大小和透明度的效果 if( value > -50.0f && value < 0) { vluA = 1.1f + value/50; imv1.setAlpha(vluA); imv1.setScaleX(vluA); imv1.setScaleY(vluA); } else { vluB = 0.1f - (value + 50.0f)/50; imv1.setAlpha(vluB); imv1.setScaleX(vluB); imv1.setScaleY(vluB); } } }); animatorBackScale.setDuration(2000); final AnimatorSet set = new AnimatorSet(); //设置几个动画的运动规则 set.play(animatorMove).with(animatorMoveScale); set.play(animatorMoveScale).before(animatorBackMove); set.play(animatorBackMove).with(animatorBackScale); set.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { //在这里实现重复运动 set.start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); set.start(); } }
所有方法的说明,其实都能在上篇找到注释说明。但是这里强调一个地方,就是AnimatorSet这个类,并没有直接提供了类似Animator的setRepeatCount() 和setRepeatMode()方法,所以如果在AnimatorSet中要实现不断重复的播放动画,就要借助AnimatorListener接口,在动画结束( end )的时候去重新调用set.start() 方法。 当然,如果AnimatorSet中的Animator已经设置了重复次数和重复模式,在AnimatorSet中依然是有效的。动画虽然简陋了些,但稍作修饰,也可以作为页面加载的动画使用,同时加深对原理的认识,在以后的使用中会更加熟练哦。大家多多练习,加油!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。