Android实现箭头无限循环上升的简单动画

需求说明

一个箭头图片在某个区域做上升的动画,到区域顶部时,消失的部分又从底部出现,如此循环往复。

先看实现的效果图,如下。
在这里插入图片描述
缺点:实际上并不是连贯的循环重复,而是第二次上升的箭头消失并没有再从底部出来,这是用简单动画实现的劣势。

优点:简单,便于理解和实现。

原理说明

用两张图片箭头一起做向上平移的动画,就可实现该功能。

一张图片放在运动区域下方,另一张图片放在运动区域的两部位置下方,然后一起使用同一个平移相同距离的动画,使之实现上述效果。
在这里插入图片描述

代码实现

首先布局设定好ImageView的具体宽高,然后用marginBottom负数的方式使之置于运动区域下方,第二个箭头margin的距离是运动区域的高度+自身的高度。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".animation.ArrowMoveActivity"
    tools:showIn="@layout/activity_arrow_move">

    <FrameLayout
        android:id="@+id/fl_move_area"
        android:background="@color/color_list_divider"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.494"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/iv_arrow_a"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:src="@mipmap/arraw_up"
            android:scaleType="centerCrop"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="-60dp"
            android:contentDescription="arrowA" />
        <ImageView
            android:id="@+id/iv_arrow_b"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:src="@mipmap/arraw_up"
            android:scaleType="centerCrop"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="-360dp"
            android:contentDescription="arrowB" />
    </FrameLayout>

</android.support.constraint.ConstraintLayout>

其次是获得向上平移的具体距离,具体距离=2倍运动区域的高度+箭头本身的高度

由于布局时写死了高度,所以可以直接得出。

/方式一:直接换算运动距离,因为高度已经限定
        //向上平移的距离计算,等于2倍运动区域高度+自身的高度
        float moveDistance = 660 * getResources().getDisplayMetrics().density;
        

还有另一种方式就是用代码计算出高度,这一定要在界面布局完成后才得测量出View的具体高度,既然要写死高度才能实现动画效果,再用代码计算就有点画蛇添足了,仅供参考。

       ivArrowA.post(new Runnable() {
           @Override
           public void run() {
                //向上平移的距离计算,等于2倍运动区域高度+自身的高度
                float moveDistance = flMoveArea.getHeight()*2 + ivArrowA.getHeight();
          }
       });

最后则是开始平移动画无限循环,记得destroy时要将之移除。

//生成一个平移动画对象,记得向上运动是负数
        Animation moveUpAnimation = new TranslateAnimation(0,0,0,-moveDistance);
        moveUpAnimation.setDuration(3000);//3秒运动完一次循环
        moveUpAnimation.setRepeatCount(Animation.INFINITE); //无限循环
        moveUpAnimation.setInterpolator(new LinearInterpolator()); //匀速运动
        //开始视图动画
        ivArrowA.startAnimation(moveUpAnimation);
        ivArrowB.startAnimation(moveUpAnimation);

总结

这个方案比较简陋一些,布局里也要设定死ImageView和运动区域的大小,相当不灵活,当然最佳的方案就是用自定义View,但暂时还没有思路实现。
如果大家有更好的解决方案,欢迎一起讨论。

最后贴上Activity的代码

package cn.pigdreams.blogdemo.animation;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;


import cn.pigdreams.blogdemo.R;

/**
 *
 */
public class ArrowMoveActivity extends AppCompatActivity {

    private FrameLayout flMoveArea;
    private ImageView ivArrowA;
    private ImageView ivArrowB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_arrow_move);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        initView();
        startArrowMove();
    }


    /**
     * 开始平移动画
     */
    private void startArrowMove() {


      //方式一:直接换算运动距离,因为高度已经限定
        //向上平移的距离计算,等于2倍运动区域高度+自身的高度
        float moveDistance = 660 * getResources().getDisplayMetrics().density;
        //生成一个平移动画对象,记得向上运动是负数
        Animation moveUpAnimation = new TranslateAnimation(0,0,0,-moveDistance);
        moveUpAnimation.setDuration(3000);//3秒运动完一次循环
        moveUpAnimation.setRepeatCount(Animation.INFINITE); //无限循环
        moveUpAnimation.setInterpolator(new LinearInterpolator()); //匀速运动
        //开始视图动画
        ivArrowA.startAnimation(moveUpAnimation);
        ivArrowB.startAnimation(moveUpAnimation);

        //方式二:代码计算运动距离,一定要等布局完成后才能开始动画
//        ivArrowA.post(new Runnable() {
//            @Override
//            public void run() {
//                //向上平移的距离计算,等于2倍运动区域高度+自身的高度
//                float moveDistance = flMoveArea.getHeight()*2 + ivArrowA.getHeight();
//                //生成一个平移动画对象,记得向上运动是负数
//                Animation moveUpAnimation = new TranslateAnimation(0,0,0,-moveDistance);
//                moveUpAnimation.setDuration(3000);//3秒运动完一次循环
//                moveUpAnimation.setRepeatCount(Animation.INFINITE); //无限循环
//                moveUpAnimation.setInterpolator(new LinearInterpolator()); //匀速运动
//                //开始视图动画
//                ivArrowA.startAnimation(moveUpAnimation);
//                ivArrowB.startAnimation(moveUpAnimation);
//            }
//        });

    }

    private void initView() {
        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        flMoveArea = findViewById(R.id.fl_move_area);
        ivArrowA = findViewById(R.id.iv_arrow_a);
        ivArrowB = findViewById(R.id.iv_arrow_b);

    }

    @Override
    protected void onDestroy() {
        ivArrowA.clearAnimation();
        ivArrowB.clearAnimation();
        super.onDestroy();
    }
}

发布了92 篇原创文章 · 获赞 68 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/pigdreams/article/details/88210853