zoukankan      html  css  js  c++  java
  • 《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();
                }
            });
        }
    }

    效果:

  • 相关阅读:
    python sys 模块
    python os 模块
    JS Dictionary
    JS Array
    JS String
    JS面向对象
    WPF中INotifyPropertyChanged用法与数据绑定
    JS的函数
    JS类型转换
    JS变量的作用域
  • 原文地址:https://www.cnblogs.com/volvane/p/10064042.html
Copyright © 2011-2022 走看看