android动画的实战篇------乐动力旋转动画

一、前言

        在现今App泛滥的市场上,各种App的功能都是你抄我的我抄你的时候,想做一个精品的App没有自己的风格,没有让用户眼前一亮的功能,或是效果的话都留步住用户了。随时都可以被其他应用替代。现今到处都喊着app简约而不简单,用户体验至上的年代,但有几个app能做到呢?可能当设计师想着想着就忘记了设计的初衷。

       吐槽半天,今天来看一下乐动力的一个比较有意思的动画效果,觉得挺爽的,然后刚好又想熟悉一下Android动画的,就拿来练下手。

二、效果图


三、动画分解

              1、中间一个变大变小的动画

              2、上下两个箭头不停的旋转

              3、左右两个小的图片不停地旋转并跟着自传就可以达到类似平移

              4、上面分解为五个Imageview并重写ViewGroup达到自定义排列

四、代码

package com.spring.ledongli;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;

public class GuideView extends ViewGroup {
	/**
	 * 左边的图片
	 */
	private ImageView left;
	/**
	 * 右边的图片
	 */
	private ImageView right;
	/**
	 * 上面的图片
	 */
	private ImageView top;
	/**
	 * 下面的图片
	 */
	private ImageView bottom;
	/**
	 * 中间的图片  m
	 */
	private ImageView center;
	/**
	 * 屏幕的宽度
	 */
	private int screenW;
	/**
	 * 屏幕的高度
	 */
	private int screenH;
	public GuideView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}
	public GuideView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}
	public GuideView(Context context) {
		super(context);
		init(context);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		setMeasuredDimension(screenW, screenH);
	}
	
	private List<Bitmap> bitmaps = new ArrayList<Bitmap>();
	private void init(Context context){
		left = new ImageView(context);
		left.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.day));
		bitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.day));
		right = new ImageView(context);
		right.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.night));
		bitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.night));
		top = new ImageView(context);
		top.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.up));
		bitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.up));
		bottom = new ImageView(context);
		bottom.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.down));
		bitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.down));
		center = new ImageView(context);
		center.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.animation_battery));
		bitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.animation_battery));
		screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth();
		screenH = ((Activity)context).getWindowManager().getDefaultDisplay().getHeight();
		this.addView(center);
		this.addView(left);
		this.addView(right);
		this.addView(top);
		this.addView(bottom);
	}
	private LinearInterpolator interpolator = new LinearInterpolator();
	@Override
	protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
		//五个控件的布局
		center.layout(screenW/2-bitmaps.get(4).getWidth()/2, screenH/2-bitmaps.get(4).getHeight()/2,  
				screenW/2+bitmaps.get(4).getWidth()/2, screenH/2+bitmaps.get(4).getHeight()/2);
		top.layout(screenW/2-bitmaps.get(2).getWidth()/2,screenH/2-bitmaps.get(4).getHeight()/2-bitmaps.get(2).getHeight()+bitmaps.get(2).getWidth()/2/4,
				screenW/2+bitmaps.get(2).getWidth()/2, screenH/2-bitmaps.get(4).getHeight()/2+bitmaps.get(2).getWidth()/2/4);
		left.layout(screenW/2-bitmaps.get(0).getWidth()*2-bitmaps.get(0).getWidth()/4, screenH/2-bitmaps.get(0).getHeight()/2,
				screenW/2-bitmaps.get(0).getWidth()-bitmaps.get(0).getWidth()/4, screenH/2+bitmaps.get(0).getHeight()/2);
		right.layout(screenW/2+bitmaps.get(1).getWidth()+bitmaps.get(1).getHeight()/4, screenH/2-bitmaps.get(1).getHeight()/2,
				screenW/2+bitmaps.get(1).getWidth()*2+bitmaps.get(1).getHeight()/4, screenH/2+bitmaps.get(1).getHeight()/2);
		bottom.layout(screenW/2-bitmaps.get(3).getWidth()/2, screenH/2+bitmaps.get(4).getHeight()/2-bitmaps.get(3).getWidth()/2/4,
				screenW/2+bitmaps.get(3).getWidth()/2, screenH/2+bitmaps.get(4).getHeight()/2+bitmaps.get(3).getHeight()-bitmaps.get(3).getWidth()/2/4);
		playCenter();
		playTop();
		playBottom();
		playLeft();
		playRight();
	}
	/**
	 * 右边的动画
	 */
	private void playRight() {
		//混合动画
		AnimationSet animationSet = new AnimationSet(false);
		RotateAnimation rotateRight = new RotateAnimation(0, 359, Animation.ABSOLUTE, screenW/2-right.getLeft(), Animation.ABSOLUTE, (right.getBottom()-right.getTop())/2);
		RotateAnimation rotateSelf = new RotateAnimation(0, -359, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f);
		//播放时间
		rotateSelf.setDuration(10*1000);
		//播放加速的模式
		rotateSelf.setInterpolator(interpolator);
		//设置无限循环
		rotateSelf.setRepeatCount(-1);
		rotateRight.setDuration(10*1000);
		rotateRight.setRepeatCount(-1);
		rotateRight.setInterpolator(interpolator);
		animationSet.addAnimation(rotateSelf);
		animationSet.addAnimation(rotateRight);
		//播放混合动画
		right.startAnimation(animationSet);
	}
	/**
	 * 左边的动画
	 */
	private void playLeft() {
		AnimationSet animationSet = new AnimationSet(false);
		RotateAnimation rotateLeft = new RotateAnimation(0, 359, Animation.ABSOLUTE, screenW/2-left.getLeft(), Animation.ABSOLUTE, (left.getBottom()-left.getTop())/2);
		rotateLeft.setDuration(10*1000);
		rotateLeft.setInterpolator(interpolator);
		rotateLeft.setRepeatCount(-1);
		RotateAnimation rotateSelf = new RotateAnimation(0, -359, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		rotateSelf.setDuration(10*1000);
		rotateSelf.setRepeatCount(-1);
		rotateSelf.setInterpolator(interpolator);
		animationSet.addAnimation(rotateSelf);
		animationSet.addAnimation(rotateLeft);
		left.startAnimation(animationSet);
	}
	/**
	 * 下面的动画
	 */
	private void playBottom() {
		RotateAnimation rotateBottom = new RotateAnimation(0, 359,  Animation.RELATIVE_TO_SELF, 0.5f, Animation.ABSOLUTE,screenH/2-bottom.getTop());
		rotateBottom.setDuration(10*1000);
		rotateBottom.setInterpolator(interpolator);
		rotateBottom.setRepeatCount(-1);
		bottom.startAnimation(rotateBottom);
	}
	/**
	 * 上面的动画
	 */
	private void playTop() {
		RotateAnimation  rotateAnimation = new RotateAnimation(0, 359, Animation.ABSOLUTE, screenW/2-top.getLeft(), Animation.ABSOLUTE, screenH/2-top.getTop());
		rotateAnimation.setDuration(10*1000);
		rotateAnimation.setInterpolator(interpolator);
		rotateAnimation.setRepeatCount(-1);
		top.startAnimation(rotateAnimation);
	}
	/**
	 * 中间的View动画播放
	 */
	private void playCenter() {
		AnimationSet animationSet = new AnimationSet(false);
		ScaleAnimation scaleSmall = new ScaleAnimation(1.0f, 0.6f, 1.0f, 0.6f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		ScaleAnimation scaleBig = new ScaleAnimation(1.0f, 5.0f/3, 1.0f, 5.0f/3,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		scaleBig.setDuration(2*1000);
		scaleBig.setInterpolator(interpolator);
		scaleSmall.setDuration(2*1000);
		scaleSmall.setStartOffset(2*1000);
		scaleSmall.setRepeatCount(-1);
		scaleSmall.setFillEnabled(true);
		scaleSmall.setFillAfter(true);
		scaleBig.setStartOffset(2*1000);
		scaleBig.setRepeatCount(-1);
		scaleBig.setFillEnabled(true);
		scaleBig.setFillAfter(true);
		scaleSmall.setInterpolator(interpolator);
		animationSet.addAnimation(scaleBig);
		animationSet.addAnimation(scaleSmall);
		center.startAnimation(animationSet);
	}

}


五、遇到的问题

写这个小Demo主要的问题在两个小太阳的自传和中点循转的结合,这方面在网上的资料也比较少,自己做了几个尝试最终完成。要很好的理解pivotXType里的三种方式Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT、Animation.ABSOLUT,第一种多用于基于自己View的几分之几来定值,第二种是基于父控件来定位,第三种是绝对定位,图片的基点在右上角,然后算偏移的值定位旋转的中间。

六、项目地址

http://download.csdn.net/detail/hxc2008q/6931227


广告

      最近搞了个微信公众号,为各种程序员枯燥的写码生活添加一些生活调料,

      在等待编译的过程看一篇美丽的图文放松放松肌肉。希望各位看官赏脸关注一下

      公众号:马桶上的哲学

      读哲名理,提升逼格


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值