上节博主介绍了AlphaAnimation和淡入淡出动画的使用,其实AlphaAnimation只是四种补间动画中的一种。那么为了加深对其他补间动画的理解,我想说说旋转动画RotateAnimation的使用,刚好工作中就有类似的应用场景,正好介绍一下。像我们生活中有许多左右摇摆的画面,比如说老式挂钟的钟摆围绕着竖轴左右摇摆,又比如说公园里人们坐在秋千上荡来荡去,这么一想,嗯,这左右摇摆的秋千动画确实贴近生活。

如果我们把钟摆或者秋千想象成一个线段,这个线段以上面的端点为圆心,先从垂直向下的角度向左旋转;转到一定角度,再向右旋转,同样旋转摆到左边的高度;接着再向左旋转,等到这个线段摆到垂直向下时,就完成了摇摆动作的一个循环。这么看,摇摆动画似乎与旋转动画有些关联,再仔细想想,这摇摆动画其实就是由三段旋转动画衔接起来的呀,先是向左旋转60度,然后向右旋转120度,最后向左旋转60度。所以看看能不能从旋转动画RotateAnimation源码中找找思路。

分析RotateAnimation的源码,我们看到RotateAnimation继承自Animation,除了几个构造函数与初始化函数之外,起主要作用的便是applyTransformation函数。

    protected void applyTransformation(float interpolatedTime, Transformation t) {float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);float scale = getScaleFactor();if (mPivotX == 0.0f && mPivotY == 0.0f) {t.getMatrix().setRotate(degrees);} else {t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);}}

该函数的输入参数interpolatedTime表示插值时间(百分比),代码内部的degrees表示在该插值时间的位置度数,scale默认1就不管了。mFromDegrees表示该动画的起始度数,mToDegrees表示该动画的终止度数,都是在初始化时传入的参数。后面代码中的mPivotX和mPivotY,前一个表示旋转圆心的X坐标,后一个表示旋转圆心的Y坐标,默认以图形左上的顶点为圆心(mPivotX=0.0f,mPivotY=0.0f)。如果不是默认圆心,则要以指定坐标为圆心进行旋转。

由此看来,摇摆动画有几个地方需要加以调整:
1、旋转动画初始化时只有两个度数:起始度数、终止度数。摇摆动画则需三个参数:中间度数(既是起始度数也是终止度数)、摆到左侧的度数、摆到右侧的度数。
2、根据插值时间估算当前所处的度数,摇摆动画需要做三个分支判断(对应之前说的摇摆动画由三段旋转动画衔接而成)。如果整个动画持续4秒,那么0-1秒之间是往左的旋转动画,起始度数为中间度数,终止度数为摆到左侧的度数;1-3秒之间是往右的旋转动画,起始度数为摆到左侧的度数,终止度数为摆到右侧的度数;3-4秒之间是往左的旋转动画,起始度数为摆到右侧的度数,终止度数为中间度数。

分析完了,贴上修改后的摇摆动画代码

import android.view.animation.Animation;
import android.view.animation.Transformation;public class SwingAnimation extends Animation {private float mMiddleDegrees;private float mLeftDegrees;private float mRightDegrees;private int mPivotXType = ABSOLUTE;private int mPivotYType = ABSOLUTE;private float mPivotXValue = 0.0f;private float mPivotYValue = 0.0f;private float mPivotX;private float mPivotY;public SwingAnimation(float middleDegrees, float leftDegrees, float rightDegrees) {mMiddleDegrees = middleDegrees;mLeftDegrees = leftDegrees;mRightDegrees = rightDegrees;mPivotX = 0.0f;mPivotY = 0.0f;}public SwingAnimation(float middleDegrees, float leftDegrees, float rightDegrees, float pivotX, float pivotY) {mMiddleDegrees = middleDegrees;mLeftDegrees = leftDegrees;mRightDegrees = rightDegrees;mPivotXType = ABSOLUTE;mPivotYType = ABSOLUTE;mPivotXValue = pivotX;mPivotYValue = pivotY;initializePivotPoint();}public SwingAnimation(float middleDegrees, float leftDegrees, float rightDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue) {mMiddleDegrees = middleDegrees;mLeftDegrees = leftDegrees;mRightDegrees = rightDegrees;mPivotXValue = pivotXValue;mPivotXType = pivotXType;mPivotYValue = pivotYValue;mPivotYType = pivotYType;initializePivotPoint();}private void initializePivotPoint() {if (mPivotXType == ABSOLUTE) {mPivotX = mPivotXValue;}if (mPivotYType == ABSOLUTE) {mPivotY = mPivotYValue;}}@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {float degrees;float leftPos = (float) (1.0/4.0);float rightPos = (float) (3.0/4.0);if (interpolatedTime <= leftPos) {degrees = mMiddleDegrees + ((mLeftDegrees - mMiddleDegrees) * interpolatedTime * 4);} else if (interpolatedTime > leftPos && interpolatedTime < rightPos) {degrees = mLeftDegrees + ((mRightDegrees - mLeftDegrees) * (interpolatedTime-leftPos) * 2);} else {degrees = mRightDegrees + ((mMiddleDegrees - mRightDegrees) * (interpolatedTime-rightPos) * 4);}System.out.println("degrees="+degrees);float scale = getScaleFactor();if (mPivotX == 0.0f && mPivotY == 0.0f) {t.getMatrix().setRotate(degrees);} else {t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);}}@Overridepublic void initialize(int width, int height, int parentWidth, int parentHeight) {super.initialize(width, height, parentWidth, parentHeight);mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);}
}

调用的代码如下

import com.example.exmswing.ui.SwingAnimation;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.ImageView;public class MainActivity extends Activity implements OnClickListener {private ImageView iv_swing;private SwingAnimation swingAnimation;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn_play = (Button) findViewById(R.id.btn_play);btn_play.setOnClickListener(this);iv_swing = (ImageView) findViewById(R.id.iv_swing);//参数取值说明:中间度数、摆到左侧的度数、摆到右侧的度数、圆心X坐标类型、圆心X坐标相对比例、圆心Y坐标类型、圆心Y坐标相对比例//坐标类型有三种:ABSOLUTE 绝对坐标,RELATIVE_TO_SELF 相对自身的坐标,RELATIVE_TO_PARENT 相对上级视图的坐标//X坐标相对比例,为0时表示左边顶点,为1表示右边顶点,为0.5表示水平中心点//Y坐标相对比例,为0时表示上边顶点,为1表示下边顶点,为0.5表示垂直中心点swingAnimation = new SwingAnimation(0f, 60f, -60f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.0f); swingAnimation.setDuration(4000);     //动画持续时间swingAnimation.setRepeatCount(0);     //动画重播次数swingAnimation.setFillAfter(false);  //是否保持动画结束画面swingAnimation.setStartOffset(500);   //动画播放延迟}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_play) {iv_swing.startAnimation(swingAnimation);}}}

下面是摇摆动画的效果图

点击下载本文用到的秋千摇摆动画代码

点此查看Android开发笔记的完整目录

Android开发笔记(十六)秋千摇摆动画SwingAnimation相关推荐

  1. Android开发笔记(六十一)文件下载管理DownloadManager

    下载管理DownloadManager 文件下载其实是网络数据访问的一种特殊形式,使用普通的http请求也能完成,就是实现起来会繁琐一些.因为下载功能比较常用,而且业务功能相对统一,所以从Androi ...

  2. Android开发笔记(十七)GIF动画的实现GifAnimation

    GIF在Windows上是常见的图片格式,主要用来播放短小的动画.但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来 ...

  3. Android开发笔记(六十五)多样的菜单

    菜单Menu Android的菜单分为两类:选项菜单和上下文菜单,默认使用选项菜单.菜单的布局文件存放在res/menu目录下,使用ADT新建一个Android工程,首页代码MainActivity中 ...

  4. Android开发笔记(六十二)HTTP数据格式的解析

    json解析 android有两种主流的json解析方案,一种是sdk自带的由Google提供的json(包名前缀为org.json),另一种是Alibaba提供的第三方jar包fastjson(包名 ...

  5. Android开发笔记(六十八)工程库打包

    写好一个Android模块,比如说一个自定义控件或某个功能的sdk,然后开放出来给别人使用,就得通过某种方式把源码提供给对方.常见的打包方式有: 一.直接给源码,由开发者把代码加入到自己的工程中 该方 ...

  6. Android开发笔记(六十六)自定义对话框

    AlertDialog Android中最常用的对话框是AlertDialog,它可以完成常见的交互操作,如提示.确认.选择等等,然后就是进度对话框ProgressDialog(参见< Andr ...

  7. Android开发笔记(六十九)JNI实战

    NDK NDK的用途 NDK全称为Native Development Kit,意即原生的开发工具,NDK允许开发者在APP中通过C/C++代码执行部分程序.它是Android提供的方便开发者通过JN ...

  8. Android开发笔记(六十四)网页加载与JS调用

    内置浏览器 网页视图WebView 如果一个网站已经有现成的网页及业务逻辑,那么使用WebView将其内嵌到app中,省去了app重画页面与http通信的事情,无疑是更经济的做法.WebView就是A ...

  9. Android开发笔记(六十三)HTTP访问的通信方式

    InputStream和OutputStream 输入输出流在java中很常用,从文件读写到内存读写到网络通信都会用到.在之前的< Android开发笔记(三十三)文本文件和图片文件的读写> ...

最新文章

  1. 【青少年编程】【四级】奇偶之和
  2. Shell 变量的操作方法
  3. 大型EAI项目中的ORACLE 数据库管理(ZT)
  4. [转载]基于TFS实践敏捷-修复Bug和执行代码评审
  5. 【HDU - 1527】【POJ - 1067】取石子游戏 (威佐夫博弈)
  6. 嵌入式系统之操作系统篇
  7. html之元素与元素的形成
  8. linux运维架构篇
  9. linux勒索病毒如何恢复数据,勒索病毒和相应的解密工具
  10. 【转】SQL修改字段长度
  11. 在HTML中什么表示水平线,HTML中加入水平线的标签是( )
  12. 可靠性 可用性 可维护性
  13. 整理归纳:《一课经济学》—— 只见树木不见森林
  14. Array Shrinking(CodeForces - 1312E )
  15. html 条纹背景,CSS3 一组条纹背景图案
  16. GeoServer结合FWTools切片工具发布影像金字塔切片
  17. php反序列化漏洞 freebuf,入门Web需要了解的PHP反序列化漏洞
  18. 只有一行VNC server running on ’::1:5900' 没有其他输出
  19. 计算机大一萌新,要补充哪些计算机基本知识
  20. Latex 编译报错: Misplaced omit.

热门文章

  1. 给 Sublime Text3 添加右键菜单
  2. 如何将自己的数据转换为Pascal voc2017数据集标注格式
  3. mysql 创建表单
  4. Kotlin协程的迷惑
  5. c语言找两个数中的最大值,不用任何比较判断找出两个数中的最大值
  6. linux ssh环境,在Linux下ssh 环境的登录 和 文件拷贝
  7. 基于Chrome浏览器的前端调试
  8. win2003安装邮箱服务器,windows2003邮件服务器
  9. java 数组以逗号分隔_在java中使用逗号分隔符拆分字符串数组
  10. docker-compose搭建ghost博客系统