android - 如何围绕圆圈为 View 设置动画?

标签 android animation

我想将围绕圆圈的无限移动动画设置为如下图所示的 View。我该如何实现?

此 View 可以是 TextView 或任何简单或复杂的 View 。

我知道我可以将我的 View 放在 ViewGroup 中并设置旋转动画,但我不想旋转 View ,因为 View 的方向很重要。

enter image description here

最佳答案

我不知道有什么可以在本地执行此操作,所以我认为您最好的方法是确定动画的路径(xy 坐标)并创建一个 Handler 来重复 postDelayed。你的处理程序每​​次迭代都会触发 translate到路径中下一个点的 View 。

编辑:我创建了一个解决方案,并通过左右移动和圆周移动对其进行了测试。

ViewPathAnimator.java:

import android.graphics.Path;
import android.graphics.PathMeasure;
import android.os.Handler;
import android.util.Pair;
import android.view.View;

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class ViewPathAnimator
{
    public static final int DEFAULT_DELAY     = 1000 / 10;
    public static final int DEFAULT_FRAMESKIP = 3;

    private static Handler                        handler;
    private static HashMap<Integer, PathRunnable> animatedViews;

    public static void animate(View view, Path path)
    {
        animate(view, path, DEFAULT_DELAY, DEFAULT_FRAMESKIP);
    }

    public static void animate(View view, Path path, int delay)
    {
        animate(view, path, delay, DEFAULT_FRAMESKIP);
    }

    public static void animate(View view, Path path, int delay, int frameSkip)
    {
        if (animatedViews == null)
        {
            animatedViews = new HashMap<>();
        }

        if (handler == null)
        {
            handler = new Handler();
        }

        if (animatedViews.containsKey(view.hashCode()))
        {
            cancel(view);
        }

        PathRunnable runnable = new PathRunnable(view, path, delay, frameSkip);
        animatedViews.put(view.hashCode(), runnable);
        handler.postDelayed(runnable, delay);
    }

    public static void cancel(View view)
    {
        if (animatedViews != null && handler != null)
        {
            PathRunnable task = animatedViews.get(view.hashCode());
            if (task != null)
            {
                handler.removeCallbacks(task);
                animatedViews.remove(view.hashCode());
            }
        }
    }

    private static class PathRunnable implements Runnable
    {
        private WeakReference<View> view;
        Pair<Float, Float>[] points;
        private int delay;
        private int frameSkip;
        private int frame;

        PathRunnable(View view, Path path, int delay, int frameSkip)
        {
            this.view = new WeakReference<>(view);
            this.points = getPoints(path);
            this.delay = delay;
            this.frameSkip = Math.max(frameSkip, 0);
            this.frame = 0;
        }

        @Override
        public void run()
        {
            frame = (frame + frameSkip + 1) % points.length;
            Pair<Float, Float> pair = points[frame];

            View v = view.get();
            if (v != null)
            {
                v.setTranslationX(pair.first);
                v.setTranslationY(pair.second);

                handler.postDelayed(this, delay);
            }
        }

        // https://stackoverflow.com/questions/7972780/how-do-i-find-all-the-points-in-a-path-in-android
        private Pair<Float, Float>[] getPoints(Path path)
        {
            PathMeasure pathMeasure = new PathMeasure(path, true);
            int         frames      = (int) pathMeasure.getLength();

            Pair<Float, Float>[] pointArray   = new Pair[frames];
            float                length       = pathMeasure.getLength();
            float                distance     = 0f;
            float                speed        = length / pointArray.length;
            int                  counter      = 0;
            float[]              aCoordinates = new float[2];

            while ((distance < length) && (counter < pointArray.length))
            {
                // get point from the path
                pathMeasure.getPosTan(distance, aCoordinates, null);
                pointArray[counter] = new Pair<>(aCoordinates[0], aCoordinates[1]);
                counter++;
                distance = distance + speed;
            }

            return pointArray;
        }
    }
}

现在可以给它一个 Graphics 路径来制作动画,就像这样

View view = findViewById(R.id.text);
Path path = new Path();
path.addCircle(0, 0, 100, Path.Direction.CW);

ViewPathAnimator.animate(view, path, 1000/ 30, 2);

关于android - 如何围绕圆圈为 View 设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33625497/

相关文章:

java - CardView动画

android - 闪烁的背景

jquery - 使用溢出调整 div 的高度

css - 是否可以为 Fontastic 自定义图标设置动画?

android - 在哪里可以找到 Android UI 组件的源代码?

android - 使用软件渲染在嵌入式平台上移植 Android

Android 6 Nexus 5 USB 连接问题

android - Linux perf stat 工具返回零指令计数。我在这里错过了什么?

android - Activity 与 Android 之间的动画

Java 动画