IOS的用户体验做的很好,其中一点很重要的地方就是动画效果。

最近在学习Android的Animation,简单实现了一个IOS相机滤镜退出的动画:

布局文件:activity_animation_demo.xml  布局未考虑各个分辨率,只是为了实现动画逻辑,(代码测试是在720P分辨率的手机上)

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context="com.example.andanimationdemo.AnimationDemoActivity" >
  6.  
  7. <FrameLayout
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_marginTop="50dp"
  11. android:layout_marginLeft="25px"
  12. android:layout_marginRight="25px"
  13. >
  14. <LinearLayout
  15. android:id="@+id/rootLinearLayout"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:orientation="vertical"
  19. >
  20. <LinearLayout
  21. android:id="@+id/firstLinearLayout"
  22. android:orientation="horizontal"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content">
  25. <Button
  26. android:id="@+id/Button_1"
  27. android:layout_width="200px"
  28. android:layout_height="200px"
  29. android:background="@android:color/holo_blue_bright"/>
  30. <Button
  31. android:id="@+id/Button_2"
  32. android:layout_width="200px"
  33. android:layout_height="200px"
  34. android:layout_marginLeft="35px"
  35. android:background="@android:color/holo_green_light"/>
  36. <Button
  37. android:layout_marginLeft="35px"
  38. android:id="@+id/Button_3"
  39. android:layout_width="200px"
  40. android:layout_height="200px"
  41. android:background="@android:color/black"/>
  42. </LinearLayout>
  43.  
  44. <LinearLayout
  45. android:id="@+id/SencondLinearLayout"
  46. android:layout_marginTop="35px"
  47. android:orientation="horizontal"
  48. android:layout_width="wrap_content"
  49. android:layout_height="wrap_content">
  50. <Button
  51. android:id="@+id/Button_4"
  52. android:layout_width="200px"
  53. android:layout_height="200px"
  54. android:background="@android:color/holo_orange_dark"/>
  55. <Button
  56. android:id="@+id/Button_5"
  57. android:layout_width="200px"
  58. android:layout_height="200px"
  59. android:layout_marginLeft="35px"
  60. android:background="@android:color/holo_red_light"/>
  61. <Button
  62. android:layout_marginLeft="35px"
  63. android:id="@+id/Button_6"
  64. android:layout_width="200px"
  65. android:layout_height="200px"
  66. android:background="@android:color/darker_gray"/>
  67. </LinearLayout>
  68.  
  69. <LinearLayout
  70. android:id="@+id/ThirdLinearLayout"
  71. android:layout_marginTop="35px"
  72. android:orientation="horizontal"
  73. android:layout_width="wrap_content"
  74. android:layout_height="wrap_content">
  75. <Button
  76. android:id="@+id/Button_7"
  77. android:layout_width="200px"
  78. android:layout_height="200px"
  79. android:background="@android:color/holo_green_light"/>
  80. <Button
  81. android:id="@+id/Button_8"
  82. android:layout_width="200px"
  83. android:layout_height="200px"
  84. android:layout_marginLeft="35px"
  85. android:background="@android:color/holo_orange_light"/>
  86. <Button
  87. android:layout_marginLeft="35px"
  88. android:id="@+id/Button_9"
  89. android:layout_width="200px"
  90. android:layout_height="200px"
  91. android:background="@android:color/holo_blue_light"/>
  92. </LinearLayout>
  93. </LinearLayout>
  94. </FrameLayout>
  95.  
  96. <Button
  97. android:id="@+id/Reset"
  98. android:layout_width="wrap_content"
  99. android:layout_height="wrap_content"
  100. android:layout_alignParentRight="true"
  101. android:layout_alignParentBottom="true"
  102. android:layout_marginRight="40dp"
  103. android:layout_marginBottom="40dp"
  104. android:text="Reset"></Button>
  105.  
  106. </RelativeLayout>

AnimationDemoActivity.java

  1. package com.example.andanimationdemo;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.view.animation.Animation;
  9. import android.view.animation.Animation.AnimationListener;
  10. import android.view.animation.ScaleAnimation;
  11. import android.widget.Button;
  12. import android.widget.LinearLayout;
  13.  
  14. public class AnimationDemoActivity extends Activity implements OnClickListener{
  15.  
  16. private static final String TAG = "AnimationDemo";
  17. LinearLayout rootLinearLayout;
  18. Button resetButton;
  19. int mCurrentClickButtonId = -1;
  20.  
  21. int[] ButtonID = new int[] {
  22. R.id.Button_1,R.id.Button_2,R.id.Button_3,
  23. R.id.Button_4,R.id.Button_5,R.id.Button_6,
  24. R.id.Button_7,R.id.Button_8,R.id.Button_9
  25. };
  26.  
  27. @Override
  28. protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.activity_animation_demo);
  31. rootLinearLayout = (LinearLayout) findViewById(R.id.rootLinearLayout);
  32. resetButton = (Button) findViewById(R.id.Reset);
  33. setButtonListener();
  34. }
  35.  
  36. private void setButtonListener() {
  37. for (int i = 0; i < ButtonID.length; i++) {
  38. rootLinearLayout.findViewById(ButtonID[i]).setOnClickListener(this);
  39. }
  40. resetButton.setOnClickListener(this);
  41. }
  42.  
  43. /**
  44. * 点击某个按钮后,开始放大动画
  45. * 这里提供的是一个思路,并不局限于当前布局,放大倍数,通过哪个点放大,都可以计算出来。
  46. */
  47. boolean onAnimationRunning = false;
  48.  
  49. public void onAnimationButtonClick() {
  50. Log.d(TAG, "onAnimationButtonClick");
  51. int[] position = new int[2];
  52. int[] ButtonPosition = new int[2];
  53. Button AnimaitonBtton = (Button) rootLinearLayout.findViewById(ButtonID[mCurrentClickButtonId - 1]);
  54. rootLinearLayout.getLocationInWindow(position);
  55. AnimaitonBtton.getLocationInWindow(ButtonPosition);
  56. int rootWidth = rootLinearLayout.getWidth();
  57. int rootHeight = rootLinearLayout.getHeight();
  58. int ButtonWidth = AnimaitonBtton.getWidth();
  59. int ButtonHeight = AnimaitonBtton.getHeight();
  60.  
  61. /**
  62. * 计算 scale factor
  63. */
  64. float widthRate = (float)rootWidth/ButtonWidth;
  65. float heightRate = (float)rootHeight/ButtonHeight;
  66.  
  67. /**
  68. * 计算放大的中心点
  69. */
  70. float PointA = (ButtonPosition[0] - position[0]) * widthRate / (widthRate - 1);
  71. float PointB = (ButtonPosition[1] - position[1]) * heightRate / (heightRate - 1);
  72.  
  73. onAnimationRunning = true;
  74. ScaleAnimation mScaleAnimation = new ScaleAnimation(1.0f, widthRate, 1.0f, heightRate,PointA,PointB);
  75. mScaleAnimation.setDuration(2000);
  76. mScaleAnimation.setFillAfter(true);
  77. mScaleAnimation.setAnimationListener(new AnimationListener() {
  78.  
  79. @Override
  80. public void onAnimationStart(Animation animation) {
  81. }
  82.  
  83. @Override
  84. public void onAnimationRepeat(Animation animation) {
  85. }
  86.  
  87. @Override
  88. public void onAnimationEnd(Animation animation) {
  89. Log.d(TAG,"onAnimationEnd");
  90. onAnimationRunning = false;
  91. for (int i = 0; i< ButtonID.length; i++) {
  92. rootLinearLayout.findViewById(ButtonID[i]).setEnabled(false);
  93. }
  94. }
  95. });
  96. rootLinearLayout.startAnimation(mScaleAnimation);
  97.  
  98. }
  99.  
  100. @Override
  101. public void onClick(View v) {
  102. // TODO Auto-generated method stub
  103. Log.d(TAG, "onClick :" + v.getId());
  104. if (onAnimationRunning) {
  105. Log.d(TAG, "onAnimationRunning = true");
  106. return;
  107. }
  108.  
  109. switch (v.getId()) {
  110. case R.id.Button_1:
  111. mCurrentClickButtonId = 1;
  112. onAnimationButtonClick();
  113. break;
  114. case R.id.Button_2:
  115. mCurrentClickButtonId = 2;
  116. onAnimationButtonClick();
  117. break;
  118. case R.id.Button_3:
  119. mCurrentClickButtonId = 3;
  120. onAnimationButtonClick();
  121. break;
  122. case R.id.Button_4:
  123. mCurrentClickButtonId = 4;
  124. onAnimationButtonClick();
  125. break;
  126. case R.id.Button_5:
  127. mCurrentClickButtonId = 5;
  128. onAnimationButtonClick();
  129. break;
  130. case R.id.Button_6:
  131. mCurrentClickButtonId = 6;
  132. onAnimationButtonClick();
  133. break;
  134. case R.id.Button_7:
  135. mCurrentClickButtonId = 7;
  136. onAnimationButtonClick();
  137. break;
  138. case R.id.Button_8:
  139. mCurrentClickButtonId = 8;
  140. onAnimationButtonClick();
  141. break;
  142. case R.id.Button_9:
  143. mCurrentClickButtonId = 9;
  144. onAnimationButtonClick();
  145. break;
  146. case R.id.Reset:
  147. mCurrentClickButtonId = -1;
  148. rootLinearLayout.clearAnimation();
  149. rootLinearLayout.postInvalidate();
  150. for (int i = 0; i< ButtonID.length; i++) {
  151. rootLinearLayout.findViewById(ButtonID[i]).setEnabled(true);
  152. }
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. }

点击某个Button后,可以通过它所在的位置坐标,以及父布局所在的位置坐标,计算出通过哪个点放大。

实现的效果如下图:

如有什么不对的地方,还望大神指正。

Android Animation学习 实现 IOS 滤镜退出动画的更多相关文章

  1. Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition

    Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...

  2. Android Animation学习(四) ApiDemos解析:多属性动画

    Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...

  3. Android Animation学习(三) ApiDemos解析:XML动画文件的使用

    Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...

  4. Android Animation学习(六) View Animation介绍

    Android Animation学习(六) View Animation介绍 View Animation View animation系统可以用来执行View上的Tween animation和F ...

  5. Android Animation学习(二) ApiDemos解析:基本Animators使用

    Android Animation学习(二) ApiDemos解析:基本Animatiors使用 Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.O ...

  6. Android Animation学习(一) Property Animation原理介绍和API简介

    Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...

  7. Android Animation学习(二) ApiDemos解析:基本Animatiors使用

    Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...

  8. Android Animation学习笔记

    原文地址: http://www.cnblogs.com/feisky/archive/2010/01/11/1644482.html 关于动画的实现,Android提供了Animation,在And ...

  9. Android animation学习笔记之view/drawable animation

    前一章中总结了android animation中property animation的知识和用法,这一章总结View animation和Drawable animation的有关知识: View ...

随机推荐

  1. 【 UVALive - 2197】Paint the Roads(上下界费用流)

    Description In a country there are n cities connected by m one way roads. You can paint any of these ...

  2. 修改Delphi工具控件的默认字体

    修改Delphi工具控件的默认字体: 注册表: Delphi 6:    HKEY_CURRENT_USER\Software\Borland\Delphi\6.0Delphi 7:    HKEY_ ...

  3. vs查看虚函数表和类内存布局

    虚继承和虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系:     虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是:class CSubClass : publ ...

  4. 全表扫描出现db file sequential read

    SESSION 1执行 SQL> update test1 set id=1000; SESSION 2 : select * from test1 如果表上面有大量的行迁链接,会是单块读等待事 ...

  5. bzoj1391

    很像最大权闭合子图的题目s向每个工作连边,流量为收益每个工序,由工作i向对应机器连边,流量为租用费每个机器向t连边,流量为购买费显然跑最小割,ans=总收益-mincut ; type node=re ...

  6. poj2954

    水题,先用叉积求三角形面积然后求三边上的点(由公约数上点)a然后用pick定理S=a+b/2-1就可以求出内部的点数了 var x,y,xx,yy,a1,a2,a3,x1,x2,x3,y1,y2,y3 ...

  7. Java第一次写的流布局图形界面,留个纪念

    package jisuanqi; import java.awt.*; public class MyFrame extends Frame{ //继承Frame类 public MyFrame() ...

  8. js遍历数组和遍历对象的区别

    <script> //----------------for用来遍历数组对象-- var i,myArr = [1,2,3]; for (var i = 0; i < myArr.l ...

  9. 使用JavaScript扫描端口

    <html>    <title>端口扫描</title>    <head></head><form><label fo ...

  10. c#基础语言编程-Path和Directory

    引言 在程序常会对文件操作,在对文件操作中需要对文件路径的进行定位,在.Net中针对寻找文件提供两个静态类以供调用,Path和Directory. Path类 来自命名空间SYstem.IO,Path ...