Android动画精讲一:从setTranslationX谈属性动画和view动画的区别

<div id="article_content" class="article_content">
 <div class="markdown_views"><p>&nbsp; &nbsp; &nbsp; &nbsp;最近又用到了动画,决定把几次项目里用到的动画走过的弯路总结一下,顺便梳理下android的动画体系。众所周知,android动画分三类:一是View 动画,又叫Tween动画,二是frame 动画(帧动画),又叫drawable 动画,三是属性动画,即property animation. <br>
 &nbsp; &nbsp; &nbsp; &nbsp;View动画,根据作用又分为缩放动画ScaleAnimation/移位动画TranslateAnimation / 透明度动画AlphaAnimation / 旋转动画RotateAnimation,这四个动画都继承android.view.animation下的Animation类。继承Animation的除了这四个类外,还有AnimationSet,关系图如下所示: <br>
 <img src="https://img-blog.csdn.net/20150821223613761" alt="这里写图片描述" title=""> <br>
 &nbsp; &nbsp; &nbsp; &nbsp;帧动画 对应AnimationDrawable类,继承自DrawableContainer,通过加载多个Drawable来一帧一帧播放达到动画效果。尽管很多人觉得这个不值一提,但是某些动画效果,如显示个小羊吃草还必须得用这个动画。 <br>
 &nbsp; &nbsp; &nbsp; &nbsp;接下来进入正题谈属性动画,该动画从android3.0引入,API11引入,是为了弥补view动画的不足。正式项目里用的话为了兼容android2.3可以用<a href="http://nineoldandroids.com/">NineOldAndroids</a>,直接将<a href="http://download.csdn.net/detail/yanzi1225627/9034115">生成的jar包放进去</a>就ok了。 <br>
 &nbsp; &nbsp; &nbsp; &nbsp;属性动画都在android.animation包下,基类是Animator类,子类为ValueAnimator和AnimatorSet(作用同view动画的AnimationSet相同),ValueAnimator的子类有ObjectAnimator和TimeAnimator,一般我们用属性动画ObjectAnimator就ok了。不妨简单对比下和view动画架构上的异同: <br>
 &nbsp; &nbsp; &nbsp; &nbsp;View动画,包名android.view.animation,基类为Animation,核心子类为TranslateAnimation,ScaleAnimation,AlphaAnimation,RotateAnimation及AnimationSet。 <br>
 &nbsp; &nbsp; &nbsp; &nbsp;Property动画,包名android.animation,基类为Animator,核心子类为AnimatorSet,ValueAnimator,ObjectAnimator,TimeAnimator。 <br>
 &nbsp; &nbsp; &nbsp; &nbsp;在详细对比属性动画和view动画前,先介绍个函数setTranslationX和setTranslationY,api版本为11,是设置view相对原始位置的偏移量,正式项目用的话考虑到兼容api11之前的用nineoldandroids里的ViewHelper即可。</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs applescript">public void setTranslationX (float translationX)
  
 Added <span class="hljs-keyword">in</span> API level <span class="hljs-number">11</span>
 Sets <span class="hljs-keyword">the</span> horizontal location <span class="hljs-keyword">of</span> this view relative <span class="hljs-keyword">to</span> <span class="hljs-keyword">its</span> left position. This effectively positions <span class="hljs-keyword">the</span> object post-layout, <span class="hljs-keyword">in</span> addition <span class="hljs-keyword">to</span> wherever <span class="hljs-keyword">the</span> object's layout placed <span class="hljs-keyword">it</span>.
  
 Related XML Attributes
 android:translationX
 Parameters
 translationX The horizontal position <span class="hljs-keyword">of</span> this view relative <span class="hljs-keyword">to</span> <span class="hljs-keyword">its</span> left position, <span class="hljs-keyword">in</span> pixels.</code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;上面是api介绍,即相对left position的偏移,所谓left position也即getLeft(),同时可以在xml里直接用android:translationX进行设置。关于view的位置,我们最常用的莫过于android:layoutMargin这一套,用来设置相对父布局的偏移,在java代码里可以通过新建或更新view的LayoutParams进行修改,如下所示:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs avrasm"> LinearLayout<span class="hljs-preprocessor">.LayoutParams</span> params = (LinearLayout<span class="hljs-preprocessor">.LayoutParams</span>)text<span class="hljs-preprocessor">.getLayoutParams</span>()<span class="hljs-comment">;</span>
 params<span class="hljs-preprocessor">.leftMargin</span> = <span class="hljs-number">0</span><span class="hljs-comment">;</span>
 params<span class="hljs-preprocessor">.rightMargin</span> = <span class="hljs-number">0</span><span class="hljs-comment">;</span>
 params<span class="hljs-preprocessor">.setMargins</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span>
 text<span class="hljs-preprocessor">.setLayoutParams</span>(params)<span class="hljs-comment">;</span></code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;之所以说有时需要新建Params而有时候需要更新,是因为有时候从view取来的params是空的,这个日后开篇文章专门谈这个问题。总之,通过view的LayoutParams设置margin最终影响了view的位置,这个同时会改变view的getLeft/getRight等变量。但通过setTranslationX改变view的位置,是不改变view的LayoutParams的,也即不改变getLeft等view的信息。 但他确实改变了view的位置,这一点可以通过获取其在window或screen的坐标,或通过getLocationInWindow及如下所示的api等到view的精确位置:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs vbnet"> <span class="hljs-keyword">text</span>.getLocationInWindow(pos);
 <span class="hljs-keyword">text</span>.getLocationOnScreen(pos);
 <span class="hljs-keyword">text</span>.getLocalVisibleRect()
 <span class="hljs-keyword">text</span>.getGlobalVisibleRect()</code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;总结: <br>
 1,setTranslationX改变了view的位置,但没有改变view的LayoutParams里的margin属性; <br>
 2,它改变的是android:translationX 属性,也即这个参数级别是和margin平行的。</p>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;下面来看这个例子,通过点击按键让一个view从最左边移动到屏幕的最右边,分别用view的TranslateAnimation和属性动画来实现。 <br>
 布局代码:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs xml"><span class="hljs-tag">&lt;<span class="hljs-title">RelativeLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span>
 <span class="hljs-attribute">xmlns:tools</span>=<span class="hljs-value">"http://schemas.android.com/tools"</span>
 <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>
 <span class="hljs-attribute">tools:context</span>=<span class="hljs-value">".MainActivity"</span>&gt;</span>
  
 <span class="hljs-tag">&lt;<span class="hljs-title">LinearLayout
 </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"50dp"</span>
 <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"@android:color/holo_green_light"</span>
 <span class="hljs-attribute">android:orientation</span>=<span class="hljs-value">"vertical"</span>&gt;</span>
  
 <span class="hljs-tag">&lt;<span class="hljs-title">TextView
 </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/text"</span>
 <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"@string/hello_world"</span> /&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-title">LinearLayout</span>&gt;</span>
  
 <span class="hljs-tag">&lt;<span class="hljs-title">Button
 </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/btn_start_anim"</span>
 <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_centerInParent</span>=<span class="hljs-value">"true"</span>
 <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"属性动画"</span> /&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-title">Button
 </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/btn_start_anim2"</span>
 <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_toLeftOf</span>=<span class="hljs-value">"@id/btn_start_anim"</span>
 <span class="hljs-attribute">android:layout_centerVertical</span>=<span class="hljs-value">"true"</span>
 <span class="hljs-attribute">android:layout_marginRight</span>=<span class="hljs-value">"40dp"</span>
 <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"复位"</span> /&gt;</span>
  
 <span class="hljs-tag">&lt;<span class="hljs-title">Button
 </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/btn_reset_pos"</span>
 <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"wrap_content"</span>
 <span class="hljs-attribute">android:layout_toRightOf</span>=<span class="hljs-value">"@id/btn_start_anim"</span>
 <span class="hljs-attribute">android:layout_centerVertical</span>=<span class="hljs-value">"true"</span>
 <span class="hljs-attribute">android:layout_marginLeft</span>=<span class="hljs-value">"40dp"</span>
 <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"复位"</span> /&gt;</span>
  
  
 <span class="hljs-tag">&lt;/<span class="hljs-title">RelativeLayout</span>&gt;</span></code></pre>
  
 <p>Java代码: <br>
 <strong>MainActivity.java</strong></p>
  
  
  
 <pre class="prettyprint"><code class=" hljs java"><span class="hljs-keyword">package</span> com.example.yanzi.myapplication;
  
 <span class="hljs-keyword">import</span> android.os.Bundle;
 <span class="hljs-keyword">import</span> android.support.v7.app.ActionBarActivity;
 <span class="hljs-keyword">import</span> android.util.Log;
 <span class="hljs-keyword">import</span> android.view.View;
 <span class="hljs-keyword">import</span> android.view.animation.TranslateAnimation;
 <span class="hljs-keyword">import</span> android.widget.Button;
 <span class="hljs-keyword">import</span> android.widget.LinearLayout;
 <span class="hljs-keyword">import</span> android.widget.TextView;
 <span class="hljs-keyword">import</span> android.widget.Toast;
  
 <span class="hljs-keyword">import</span> com.nineoldandroids.animation.Animator;
 <span class="hljs-keyword">import</span> com.nineoldandroids.animation.ObjectAnimator;
 <span class="hljs-keyword">import</span> com.nineoldandroids.view.ViewHelper;
 <span class="hljs-keyword">import</span> com.yanzi.util.UiUtil;
  
  
 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ActionBarActivity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">View</span>.<span class="hljs-title">OnClickListener</span>{</span>
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"YanZi"</span>;
  
 Button btn_start_anim;
 Button btn_reset_pos;
 Button btn_start_anim2;
 TextView text;
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
 <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 initData();
 initUI();
 }
  
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initData</span>(){
 UiUtil.initialize(getApplicationContext());
 }
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initUI</span>(){
 btn_start_anim = (Button)findViewById(R.id.btn_start_anim);
 btn_start_anim.setOnClickListener(<span class="hljs-keyword">this</span>);
 btn_start_anim2 = (Button)findViewById(R.id.btn_start_anim2);
 btn_start_anim2.setOnClickListener(<span class="hljs-keyword">this</span>);
 btn_reset_pos = (Button)findViewById(R.id.btn_reset_pos);
 btn_reset_pos.setOnClickListener(<span class="hljs-keyword">this</span>);
 text = (TextView)findViewById(R.id.text);
 text.setOnClickListener(<span class="hljs-keyword">this</span>);
 LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)text.getLayoutParams();
 params.leftMargin = <span class="hljs-number">0</span>;
 params.rightMargin = <span class="hljs-number">0</span>;
 params.setMargins(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
 text.setLayoutParams(params);
  
 }
  
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(View v) {
 <span class="hljs-keyword">switch</span> (v.getId()){
 <span class="hljs-keyword">case</span> R.id.btn_start_anim:
 playAnim1();
 <span class="hljs-keyword">break</span>;
 <span class="hljs-keyword">case</span> R.id.btn_start_anim2:
 playAnim2();
 <span class="hljs-keyword">break</span>;
 <span class="hljs-keyword">case</span> R.id.btn_reset_pos:
 resetPos();
 <span class="hljs-keyword">break</span>;
 <span class="hljs-keyword">case</span> R.id.text:
 printParams();
 <span class="hljs-keyword">break</span>;
 <span class="hljs-keyword">default</span>:<span class="hljs-keyword">break</span>;
 }
 }
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printParams</span>(){
 LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)text.getLayoutParams();
 <span class="hljs-keyword">if</span>(params != <span class="hljs-keyword">null</span>){
 String s = <span class="hljs-string">"leftMargin = "</span> + params.leftMargin + <span class="hljs-string">" rightMargin = "</span> + params.rightMargin
 + <span class="hljs-string">" getLeft = "</span> + text.getLeft() + <span class="hljs-string">" getRight = "</span> + text.getRight() + <span class="hljs-string">" getWidth = "</span> + text.getWidth();
 Log.i(TAG, s);
 <span class="hljs-keyword">int</span>[] pos = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">2</span>];
 text.getLocationInWindow(pos);
 Log.i(TAG, <span class="hljs-string">"location, x = "</span> + pos[<span class="hljs-number">0</span>] + <span class="hljs-string">" y = "</span> + pos[<span class="hljs-number">1</span>]);
 Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
 }
 }
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playAnim1</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 <span class="hljs-keyword">int</span> transX = screenW - w;
 ObjectAnimator transAnim = ObjectAnimator.ofFloat(text, <span class="hljs-string">"translationX"</span>, <span class="hljs-number">0</span>, transX);
 transAnim.addListener(<span class="hljs-keyword">new</span> Animator.AnimatorListener() {
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationStart</span>(Animator animator) {
  
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationEnd</span>(Animator animator) {
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationCancel</span>(Animator animator) {
  
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationRepeat</span>(Animator animator) {
  
 }
 });
 transAnim.setDuration(<span class="hljs-number">300</span>);
 transAnim.start();;
 }
  
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playAnim2</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 <span class="hljs-keyword">int</span> transX = screenW - w;
 TranslateAnimation transAnim = <span class="hljs-keyword">new</span> TranslateAnimation(<span class="hljs-number">0</span>, transX, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
 transAnim.setDuration(<span class="hljs-number">300</span>);
 text.setAnimation(transAnim);
 transAnim.start();
  
 }
  
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">resetPos</span>(){
 ViewHelper.setTranslationX(text, <span class="hljs-number">0</span>);
 }
 }</code></pre>
  
 <p>用到了一个辅助类获得屏幕的宽高和dip转px:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs java"><span class="hljs-keyword">package</span> com.yanzi.util;
  
 <span class="hljs-keyword">import</span> android.content.Context;
 <span class="hljs-keyword">import</span> android.util.DisplayMetrics;
 <span class="hljs-keyword">import</span> android.util.Log;
 <span class="hljs-keyword">import</span> android.view.View;
 <span class="hljs-keyword">import</span> android.view.ViewGroup;
 <span class="hljs-keyword">import</span> android.view.WindowManager;
 <span class="hljs-keyword">import</span> android.widget.ListAdapter;
 <span class="hljs-keyword">import</span> android.widget.ListView;
  
 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UiUtil</span> {</span>
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"YanZi_UiUtil"</span>;
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> screenWidth = <span class="hljs-number">0</span>;
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> screenHeight = <span class="hljs-number">0</span>;
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">float</span> screenDensity = <span class="hljs-number">0</span>;
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> densityDpi = <span class="hljs-number">0</span>;
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> statusBarHeight = <span class="hljs-number">0</span>;
  
  
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initialize</span>(Context context){
 <span class="hljs-keyword">if</span> (context == <span class="hljs-keyword">null</span>)
 <span class="hljs-keyword">return</span>;
 DisplayMetrics metrics = <span class="hljs-keyword">new</span> DisplayMetrics();
 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
 wm.getDefaultDisplay().getMetrics(metrics);
 screenWidth = metrics.widthPixels; <span class="hljs-comment">// 屏幕宽度</span>
 screenHeight = metrics.heightPixels; <span class="hljs-comment">// 屏幕高度</span>
 screenDensity = metrics.density; <span class="hljs-comment">// 0.75 / 1.0 / 1.5 / 2.0 / 3.0</span>
 densityDpi = metrics.densityDpi; <span class="hljs-comment">//120 160 240 320 480</span>
 Log.i(TAG, <span class="hljs-string">"screenDensity = "</span> + screenDensity + <span class="hljs-string">" densityDpi = "</span> + densityDpi);
 }
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">dip2px</span>(<span class="hljs-keyword">float</span> dipValue){
 <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>)(dipValue * screenDensity + <span class="hljs-number">0.5</span>f);
 }
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">px2dip</span>(<span class="hljs-keyword">float</span> pxValue){
  
 <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>)(pxValue / screenDensity + <span class="hljs-number">0.5</span>f);
 }
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getScreenWidth</span>() {
 <span class="hljs-keyword">return</span> screenWidth;
 }
  
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getScreenHeight</span>() {
 <span class="hljs-keyword">return</span> screenHeight;
 }
  
 }</code></pre>
  
 <p>运行界面: <br>
 <img src="https://img-blog.csdn.net/20150822003412352" alt="这里写图片描述" title=""></p>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;大概说下里面核心的几个函数: <br>
 1,使用view动画TranslateAnimation:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs cs"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playAnim2</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 <span class="hljs-keyword">int</span> transX = screenW - w;
 TranslateAnimation transAnim = <span class="hljs-keyword">new</span> TranslateAnimation(<span class="hljs-number">0</span>, transX, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
 transAnim.setDuration(<span class="hljs-number">300</span>);
 text.startAnimation(transAnim);
 }</code></pre>
  
 <p>2,使用属性动画移位:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs java"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playAnim1</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 <span class="hljs-keyword">int</span> transX = screenW - w;
 ObjectAnimator transAnim = ObjectAnimator.ofFloat(text, <span class="hljs-string">"translationX"</span>, <span class="hljs-number">0</span>, transX);
 transAnim.addListener(<span class="hljs-keyword">new</span> Animator.AnimatorListener() {
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationStart</span>(Animator animator) {
  
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationEnd</span>(Animator animator) {
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationCancel</span>(Animator animator) {
  
 }
  
 <span class="hljs-annotation">@Override</span>
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationRepeat</span>(Animator animator) {
  
 }
 });
 transAnim.setDuration(<span class="hljs-number">300</span>);
 transAnim.start();;
 }</code></pre>
  
 <p>3,点击text打印它的坐标:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs avrasm"> public void printParams(){
 LinearLayout<span class="hljs-preprocessor">.LayoutParams</span> params = (LinearLayout<span class="hljs-preprocessor">.LayoutParams</span>)text<span class="hljs-preprocessor">.getLayoutParams</span>()<span class="hljs-comment">;</span>
 if(params != null){
 String s = <span class="hljs-string">"leftMargin = "</span> + params<span class="hljs-preprocessor">.leftMargin</span> + <span class="hljs-string">" rightMargin = "</span> + params<span class="hljs-preprocessor">.rightMargin</span>
 + <span class="hljs-string">" getLeft = "</span> + text<span class="hljs-preprocessor">.getLeft</span>() + <span class="hljs-string">" getRight = "</span> + text<span class="hljs-preprocessor">.getRight</span>() + <span class="hljs-string">" getWidth = "</span> + text<span class="hljs-preprocessor">.getWidth</span>()<span class="hljs-comment">;</span>
 Log<span class="hljs-preprocessor">.i</span>(TAG, s)<span class="hljs-comment">;</span>
 int[] pos = new int[<span class="hljs-number">2</span>]<span class="hljs-comment">;</span>
 text<span class="hljs-preprocessor">.getLocationInWindow</span>(pos)<span class="hljs-comment">;</span>
 Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"location, x = "</span> + pos[<span class="hljs-number">0</span>] + <span class="hljs-string">" y = "</span> + pos[<span class="hljs-number">1</span>])<span class="hljs-comment">;</span>
 Toast<span class="hljs-preprocessor">.makeText</span>(getApplicationContext(), s, Toast<span class="hljs-preprocessor">.LENGTH</span>_LONG)<span class="hljs-preprocessor">.show</span>()<span class="hljs-comment">;</span>
 }
 }</code></pre>
  
 <p>4,使用属性动画后如果想复位:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs cs"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">resetPos</span>(){
 ViewHelper.setTranslationX(text, <span class="hljs-number">0</span>);
 }</code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;直接将translationX设为0即可,而不是上次偏移量的相反数。正因为如此,重复点击属性动画,看到view每次都从最左边到最右边,并最终停在最右边。因为属性动画的执行过程就是setTranslationX(0), 1, 2, 3, 4,……..N的过程,所以才会有看到的效果。</p>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;另外,可以看到使用view的TranslateAnimation动画播放完毕后,view瞬间又回到了原点;而使用属性动画移位后view位置确实发生了改变。但LayoutParams里的margin和getLeft信息并未改变。有没有办法让view的TranslateAnimation播放完毕后,停在那个地方呢?</p>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;肯定是有,加上这句话:transAnim.setFillAfter(true);之后运行发现view确实停在了屏幕的右侧,但是点击右侧的textview并没有触发打印参数的函数,而点击textview的初始位置才触发。所以它并没有改变view的位置,仅仅是绘制在了屏幕的右侧。因此,如果使用view动画但又想真正改变view位置需要如下代码:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs cs"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playAnim2</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 <span class="hljs-keyword">int</span> transX = screenW - w;
 TranslateAnimation transAnim = <span class="hljs-keyword">new</span> TranslateAnimation(<span class="hljs-number">0</span>, transX, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
 transAnim.setDuration(<span class="hljs-number">300</span>);
 <span class="hljs-comment">// transAnim.setFillAfter(true);</span>
 transAnim.setAnimationListener(<span class="hljs-keyword">new</span> Animation.AnimationListener() {
 @Override
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationStart</span>(Animation animation) {
  
 }
  
 @Override
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationEnd</span>(Animation animation) {
 updateParams();
 }
  
 @Override
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAnimationRepeat</span>(Animation animation) {
  
 }
 });
 text.startAnimation(transAnim);
 }
  
  
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateParams</span>(){
 <span class="hljs-keyword">int</span> w = text.getWidth();
 <span class="hljs-keyword">int</span> screenW = UiUtil.getScreenWidth();
 LinearLayout.LayoutParams <span class="hljs-keyword">params</span> = (LinearLayout.LayoutParams) text.getLayoutParams();
 <span class="hljs-keyword">params</span>.leftMargin = screenW - w;
 text.setLayoutParams(<span class="hljs-keyword">params</span>);
 }</code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;即使用LayoutParams在动画结束后设置下就ok了,这样也能达到属性动画改变view的位置的效果。view 动画+updateParams 约等于property动画效果。 <br>
 &nbsp; &nbsp; &nbsp; &nbsp;但是切忌,使用view动画+updateParams策略时,务必注意不要使用transAnim.setFillAfter(true);这句话,先看看setFillAfter的api:</p>
  
  
  
 <pre class="prettyprint"><code class=" hljs applescript">If fillAfter <span class="hljs-keyword">is</span> <span class="hljs-constant">true</span>, <span class="hljs-keyword">the</span> transformation <span class="hljs-keyword">that</span> this animation performed will persist when <span class="hljs-keyword">it</span> <span class="hljs-keyword">is</span> finished. Defaults <span class="hljs-keyword">to</span> <span class="hljs-constant">false</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">set</span>. Note <span class="hljs-keyword">that</span> this applies <span class="hljs-keyword">to</span> individual animations <span class="hljs-keyword">and</span> when using an AnimationSet <span class="hljs-keyword">to</span> chain animations.
  
 Related XML Attributes
 android:fillAfter
 Parameters
 fillAfter <span class="hljs-constant">true</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">the</span> animation should apply <span class="hljs-keyword">its</span> transformation <span class="hljs-keyword">after</span> <span class="hljs-keyword">it</span> ends</code></pre>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;如果为true,动画结束后关于view的变换会一直存在。在view动画+updateParams+transAnim.setFillAfter(true)这种策略下,view最终的绘制位置等于将view先updateParams后在新的位置基础上,再进行动画移位,一般情况下这并不是我们想要的! <br>
 &nbsp; &nbsp; &nbsp; &nbsp;基本上可以这么说,如果需要view位置真正改变setFillAfter一定不要设! <br>
 &nbsp; &nbsp; &nbsp; &nbsp;时间原因,很多东西只有下次再写了,关于属性动画和view动画详细对比可以参考<a href="http://developer.android.com/intl/zh-cn/guide/topics/graphics/prop-animation.html#property-vs-view">官方文档</a>里How Property Animation Differs from View Animation这一段,见后文。</p>
  
 <p>&nbsp; &nbsp; &nbsp; &nbsp;总之,要知其然并知其所以然,不要一味否定view动画而肯定属性动画。很多多个界面间的复杂效果非view动画不可,用属性动画只能掉坑里,我是两种坑都掉过。如果想改变动画后view的属性,如位置,可以用属性动画也可以用view动画+updateParams,当然前者更省事。在有些情况下,仅仅是想得到动画的呈现,动画结束后的位置就是view的初始位置,如view从一个地方飞过来,动画结束时view的位置就是view的位置时,此时view动画最合适!</p>
  
 <blockquote>
 <p>The view animation system provides the capability to only animate View objects, so if you wanted to animate non-View objects, you have to implement your own code to do so. The view animation system is also constrained in the fact that it only exposes a few aspects of a View object to animate, such as the scaling and rotation of a View but not the background color, for instance.</p>
  
 <p>Another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. For instance, if you animated a button to move across the screen, the button draws correctly, but the actual location where you can click the button does not change, so you have to implement your own logic to handle this.</p>
  
 <p>With the property animation system, these constraints are completely removed, and you can animate any property of any object (Views and non-Views) and the object itself is actually modified. The property animation system is also more robust in the way it carries out animation. At a high level, you assign animators to the properties that you want to animate, such as color, position, or size and can define aspects of the animation such as interpolation and synchronization of multiple animators.</p>
  
 <p>The view animation system, however, takes less time to setup and requires less code to write. If view animation accomplishes everything that you need to do, or if your existing code already works the way you want, there is no need to use the property animation system. It also might make sense to use both animation systems for different situations if the use case arises.</p>
 </blockquote>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值