《Android开发艺术探索》读书笔记——Cha3.2.2使用动画实现View的滑动

章节来自《Android开发艺术探索》

第一种方式

3.2.2 使用动画

上一节介绍了采用scrollTo/scrollBy来实现View的滑动,本节介绍另外一种滑动方式,即使用动画,通过动画我们能够让一个View进行平移,而平移就是一种滑动。使用动画来移动View,主要是操作View的translationX和translationY属性,既可以采用传统的View动画,也可以采用属性动画,如果采用属性动画的话,为了能够兼容3.0以下的版本,需要采用开源动画库nineoldandroids(http://nineoldandroids.com/)。

采用View动画的代码,如下所示。此动画可以在100ms内将一个View从原始位置向右下角移动100个像素。

    <?xml version="1.0" encoding="utf-8"?>

    <set xmlns:android="http://schemas.android.com/apk/res/android"

         android:fillAfter="true"

         android:zAdjustment="normal" >

         <translate

             android:duration="100"

             android:fromXDelta="0"

             android:fromYDelta="0"

             android:interpolator="@android:anim/linear_interpolator"

             android:toXDelta="100"

             android:toYDelta="100" />

    </set>

 

在res/下创建anim目录,再创建animation_test.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:zAdjustment="normal" >
    <!--默认为@android:anim/accelerate_decelerate_interpolator,即加速减速插值器,-->
    <!--android:duration="10000" 10秒,为了看出速度先快后慢,是使用默认插值器的效果-->
    <translate
        android:duration="5000"
        android:fromXDelta="0"
        android:fromYDelta="0"

        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="500"
        android:toYDelta="500" />

</set>

MainActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.tv);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.animation_test);
                textView.startAnimation(animation);

            }
        });
    }
}

 

 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv"
        android:text="click me"
        android:background="@color/colorPrimary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    
</LinearLayout>

 效果

 

注意:

上面提到View动画并不能真正改变View的位置,这会带来一个很严重的问题。试想一下,比如我们通过View动画将一个Button向右移动100px,并且这个View设置的有单击事件,然后你会惊奇地发现,单击新位置无法触发onClick事件,而单击原始位置仍然可以触发onClick事件,尽管Button已经不在原始位置了。这个问题带来的影响是致命的,但是它却又是可以理解的,因为不管Button怎么做变换,但是它的位置信息(四个顶点和宽/高)并不会随着动画而改变,因此在系统眼里,这个Button并没有发生任何改变,它的真身仍然在原始位置。在这种情况下,单击新位置当然不会触发onClick事件了,因为Button的真身并没有发生改变,在新位置上只是View的影像而已。基于这一点,我们不能简单地给一个View做平移动画并且还希望它在新位置继续触发一些单击事件。

 

从Android 3.0开始,使用属性动画可以解决上面的问题,但是大多数应用都需要兼容到Android 2.2,在Android 2.2上无法使用属性动画,因此这里还是会有问题。那么这种问题难道就无法解决了吗?也不是的,虽然不能直接解决这个问题,但是还可以间接解决这个问题,这里给出一个简单的解决方法。针对上面View动画的问题,我们可以在新位置预先创建一个和目标Button一模一样的Button,它们不但外观一样连onClick事件也一样。当目标Button完成平移动画后,就把目标Button隐藏,同时把预先创建的Button显示出来,通过这种间接的方式我们解决了上面的问题。这仅仅是个参考,面对这种问题时读者可以灵活应对。

第二种方式

如果采用属性动画的话,就更简单了,以下代码可以将一个View在100ms内从原始位置向右平移100像素。

    ObjectAnimator.ofFloat(targetView,"translationX",0,100).setDuration

     (100).start();

 

修改MainActivity.java

package com.example.wuf.overdrawtest;

import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.tv);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.animation_test);
//                textView.startAnimation(animation);
                ObjectAnimator.ofFloat(textView,"translationX",0,500).setDuration
                        (5000).start();
                ObjectAnimator.ofFloat(textView,"translationY",0,500).setDuration
                        (5000).start();
            }
        });
    }
}

效果:

 

posted @ 2018-12-04 14:45  Volvane  阅读(192)  评论(0编辑  收藏  举报
回顶部
//回顶部