美文网首页
【Android初级】如何实现一个比相册更高大上的左右滑动特效(

【Android初级】如何实现一个比相册更高大上的左右滑动特效(

作者: snowyeti | 来源:发表于2021-02-02 22:52 被阅读0次

    在Android里面,想要实现一个类似相册的左右滑动效果,我们除了可以用Gallery、HorizontalScrollView、ViewPager等控件,还可以用一个叫做 ViewFlipper 的类来代替实现,它继承于 ViewAnimator。如见其名,这个类是跟动画有关,会将添加到它里面的两个或者多个View做一个动画,然后每次只显示一个子View,通过在 View 之间切换时执行动画,最终达到一个类似相册能左右滑动的效果。

    本次功能要实现的两个基本效果

    1. 最基本的左右滑动效果
    2. 从屏幕的45度方向进入和退出的效果

    实现思路

    1. 按照 ViewFlipper 的源码说明,它是将两个或多个View用动画展示出来。那么我就在 ViewFlipper 内放入两个布局,每个布局都包含一个 TextView 和 ImageView,分别用于显示文字和图片
    2. 既然要有动画效果,我准备使用Android的位移动画类 TranslateAnimation,设置起始的横纵坐标值
    3. 为了让效果明显,我会设置 ViewFlipper 的进入和退出屏幕的动画,并且在左滑时呈现一个动画、右滑时呈现另一个动画(需要判断是左滑还是右滑:重写 onTouchEvent 方法,比较横坐标X的值的变化)

    源码如下:

    1、主Activity

    // import语句省略
    public class ViewFlipperDemo extends Activity {
        private static final String TAG = "ViewFlipperDemo";
    
        private ViewFlipper mViewFlipper;
        private float mOldTouchValue;
    
        @Override
        protected void onCreate(Bundle onSavedInstance) {
            super.onCreate(onSavedInstance);
    
            // 设置为全屏
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.view_flipper_demo);
            mViewFlipper = findViewById(R.id.viewFlipper1);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mOldTouchValue = event.getX();
                    break;
    
                    case MotionEvent.ACTION_UP:
                        float currentX = event.getX();
    
                        // 手指向右滑动: 手指向右滑动时横坐标 X 的值会变大,因此 currentX 的值更大
                        if (mOldTouchValue < currentX) {
    
                            // 进入屏幕的动效
                            mViewFlipper.setInAnimation(AnimationHelper.inFromLeftAnimation());
    
                            // 退出屏幕的动效
                            mViewFlipper.setOutAnimation(AnimationHelper.outToRightAnimation());
                            mViewFlipper.showNext();
                        }
    
                        // 横坐标的值变小,说明是左滑
                        if (mOldTouchValue > currentX) {
    
                            // 进入屏幕的动效
                            mViewFlipper.setInAnimation(AnimationHelper.inFromRightAnimation());
    
                            // 退出屏幕的动效
                            mViewFlipper.setOutAnimation(AnimationHelper.outToLeftAnimation());
                            mViewFlipper.showPrevious();
                        }
                        break;
    
                    default:
                        break;
            }
            return super.onTouchEvent(event);
        }
    }
    

    2、对应的布局文件 view_flipper_demo.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">
    
        <TextView android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:textColor="@color/colorBlack"
                  android:gravity="center"
                  android:text="这是一个ViewFlipper样例"
                  android:paddingTop="20dp"/>
    
        <ViewFlipper android:layout_width="match_parent"
                     android:layout_height="match_parent"
                     android:id="@+id/viewFlipper1">
    
            <LinearLayout android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:orientation="vertical"
                          android:gravity="center">
    
                <TextView android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:textColor="@color/colorBlue"
                          android:gravity="center"
                          android:text="这是第一个ViewFlipper页面"/>
    
                <ImageView android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:src="@drawable/avasterdr"/>
    
            </LinearLayout>
    
            <LinearLayout android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:orientation="vertical"
                          android:gravity="center" >
    
                <TextView android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:textColor="@color/colorBlue"
                          android:gravity="center"
                          android:text="这是第二个ViewFlipper页面"/>
    
                <ImageView android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:src="@drawable/avastertony"/>
    
            </LinearLayout>
    
        </ViewFlipper>
    
    </LinearLayout>
    

    3、动画辅助类 AnimationHelper.java

    public class AnimationHelper {
    
        // 左滑的进入动画
        public static Animation inFromRightAnimation() {
            Animation inFromRight = new TranslateAnimation(
                    Animation.RELATIVE_TO_PARENT,
                    1.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f);
            inFromRight.setDuration(500);
            inFromRight.setInterpolator(new AccelerateInterpolator());
            return inFromRight;
        }
    
        // 左滑的退出动画
        public static Animation outToLeftAnimation() {
            Animation outToLeft = new TranslateAnimation(
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    -1.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f);
            outToLeft.setDuration(500);
            outToLeft.setInterpolator(new AccelerateInterpolator());
            return outToLeft;
        }
    
        // 右滑的进入动画
        public static Animation inFromLeftAnimation() {
            Animation inFromLeft = new TranslateAnimation(
                    Animation.RELATIVE_TO_PARENT,
                    -1.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f);
            inFromLeft.setDuration(500);
            inFromLeft.setInterpolator(new AccelerateInterpolator());
            return inFromLeft;
        }
    
        // 右滑的退出动画
        public static Animation outToRightAnimation() {
            Animation outToRight = new TranslateAnimation(
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    1.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f,
                    Animation.RELATIVE_TO_PARENT,
                    0.0f);
            outToRight.setDuration(500);
            outToRight.setInterpolator(new AccelerateInterpolator());
            return outToRight;
        }
    }
    

    4、对应的效果图如下

    可以看到,这个左右滑动效果没有任何酷炫的地方。我们不妨先来看看跟动画相关的几个重点地方:

    (1)函数 setInAnimation:是指 View 进入屏幕的动效

    (2)函数 setOutAnimation:是指 View 退出屏幕的动效

    (3)TranslateAnimation的构造函数的参数解释:

    1、fromXType/toXType/fromYType/toYType,取值共有三个:

    • Animation.ABSOLUTE
    • Animation.RELATIVE_TO_SELF
    • Animation.RELATIVE_TO_PARENT

    我这里用的是 Animation.RELATIVE_TO_PARENT,当传入该参数时,其余几个坐标值需要传入百分比参数(1.0表示100%);如果传入 Animation.ABSOLUTE,坐标值需要传入屏幕上的绝对位置(比如1000,1000)

    2、fromXValue:起点的横坐标值

    3、toXValue:终点的横坐标值

    4、fromYValue:起点的纵坐标值

    5、toYValue:终点的纵坐标值

    如果我们想让这个效果变成45度从屏幕的四个角进入和退出,那代码就应该这么写(注意代码中传入的 4 个横纵坐标值):

    // 左滑的进入动画
    public static Animation inFromRightAnimation() {
        Animation inFromRight = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT,
                1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                -1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f);
        inFromRight.setDuration(500);
        inFromRight.setInterpolator(new AccelerateInterpolator());
        return inFromRight;
    }
    
    // 左滑的退出动画
    public static Animation outToLeftAnimation() {
        Animation outToLeft = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                -1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                1.0f);
        outToLeft.setDuration(500);
        outToLeft.setInterpolator(new AccelerateInterpolator());
        return outToLeft;
    }
    
    // 右滑的进入动画
    public static Animation inFromLeftAnimation() {
        Animation inFromLeft = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT,
                -1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                -1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f);
        inFromLeft.setDuration(500);
        inFromLeft.setInterpolator(new AccelerateInterpolator());
        return inFromLeft;
    }
    
    // 右滑的退出动画
    public static Animation outToRightAnimation() {
        Animation outToRight = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                1.0f,
                Animation.RELATIVE_TO_PARENT,
                0.0f,
                Animation.RELATIVE_TO_PARENT,
                1.0f);
        outToRight.setDuration(500);
        outToRight.setInterpolator(new AccelerateInterpolator());
        return outToRight;
    }
    

    对应的效果如下:

    之所以有 -1.0f 这个值,是因为屏幕上的横纵坐标值的分布可以用如下象限来表示:

    ViewFlipper中的 View 就位于象限的中心位置。因此,如果动画从左上角进入,那么它的起始横纵坐标就是(-1,-1)。大家可以按照这个思路去实现自己想要的动效。

    欢迎交流~

    相关文章

      网友评论

          本文标题:【Android初级】如何实现一个比相册更高大上的左右滑动特效(

          本文链接:https://www.haomeiwen.com/subject/uevutltx.html