Android实现环绕动画

鸿蒙的学习暂且搁置了好几个月了。最近来的android的新项目。鸿蒙的加密和解密遇到一点问题。卡住了。正好这些天做了安卓项目。

安卓项目要实现一个环绕动画。查了很多资料始终没有找到合适的效果。最后在一位兄弟那里找到了自定义的动画。可惜没法点击。我自己把点击事件给加进去了。先上个效果看看。

android动画旋转效果

参考了大佬的自定义view。我修改以后加了点击事件的判断。

大佬的文章链接在这里:

Android实现旋转动画的两种方式_android 旋转动画-CSDN博客

大家可以去看大佬的原文。因为我这边的 需求是要点击某一个图片有响应。去跳转不同的产品页。大佬用的是自己画的小球。这里我改成了自己的图片。然后加了点击事件。用第一种方法实现的。第二种画布旋转的找不到点击的位置还有小球的坐标。上源码。大家可以参考下:

package com.hyw.twelveanimals.view;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.hyw.twelveanimals.R;
import com.hyw.twelveanimals.model.StringModel;
import com.hyw.twelveanimals.model.PointCircle;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;

import androidx.annotation.Nullable;


/**

 
 * @author 最终版本---------点击坐标有响应                                                                                                                         />
 *
 *
 *
 */
public class MyRotateSelectView extends View {

    //设置旋转间隔时间
    private int SPLASH_CIRCLE_ROTATE_TIME = 30000;
    //设置中心圆半径
    private float CENTER_CIRCLE_RADIUS;
    private float SMALL_CIRCLE_RADIUS;
    private float mCurrentSingle = 0f;
    private Paint mCirclePaint;
    private ValueAnimator va;
    int[] resArray = new int[]{R.drawable.anima1, R.drawable.anima2, R.drawable.anima3, R.drawable.anima4, R.drawable.anima5, R.drawable.anima6};
    ArrayList<Bitmap> scaledBitmaps = new ArrayList<>();

    public MyRotateSelectView(Context context) {
        super(context);
    }

    public MyRotateSelectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRotateSelectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        //初始化参数
        initParams(width, height);

        setMeasuredDimension(width, height);
    }

    private void initParams(int w, int h) {
        //设置中心圆半径
        CENTER_CIRCLE_RADIUS = 1 / 3.5f * w;
        //设置小圆的半径
        SMALL_CIRCLE_RADIUS = 90;

        //初始化画笔
        mCirclePaint = new Paint();

        for (int i = 0; i < resArray.length; i++) {
            Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), resArray[i]);
            int desiredWidth = 180;
            int desiredHeight = 180;
            Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, desiredWidth, desiredHeight, true);
            scaledBitmaps.add(scaledBitmap);
        }
    }

    ArrayList<PointCircle> arrayList = new ArrayList<>();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制圆
        drawSplashCircle(canvas);
    }

    private void drawSplashCircle(Canvas canvas) {
        //设置属性动画,让小圆转起来
        //这里得注意,是个坑,你如果不判断那球就不会动 因为会陷入死循环 值动画将值设置为0 -> invalidate()重绘 -> 执行draw 又将值设为0
        if (va == null) {
            va = ObjectAnimator.ofFloat(0f, 2 * (float) Math.PI);
            va.setDuration(SPLASH_CIRCLE_ROTATE_TIME);
            va.setRepeatCount(ValueAnimator.INFINITE);
            va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mCurrentSingle = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            va.setInterpolator(new LinearInterpolator());
            va.start();
        }

        //计算每个小球的间隔
        double spaceAngle = Math.PI * 2 / resArray.length;

        arrayList.clear();
        for (int i = 0; i < resArray.length; i++) {

            //利用 勾股定理 计算 小圆 中心点
            float cx = getWidth() / 2  + (float) ((CENTER_CIRCLE_RADIUS) * Math.cos(spaceAngle * i + mCurrentSingle))-90;
            float cy = getHeight() / 2  + (float) ((CENTER_CIRCLE_RADIUS) * Math.sin(spaceAngle * i + mCurrentSingle))-90;

            canvas.drawBitmap(scaledBitmaps.get(i), cx, cy, mCirclePaint);
            arrayList.add(new PointCircle(cx, cy, i));
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 获取点击位置
                float x = event.getX();
                float y = event.getY();
                Log.e("222", "onTouchEvent: x==" + x + "  y==" + y);
                isInCircle(x, y);
                break;
        }
        return true;
    }

    private boolean isInCircle(float x, float y) {
        // 计算点到圆心的距离
        for (int i = 0; i < arrayList.size(); i++) {
            float cx = arrayList.get(i).getCx();
            float cy = arrayList.get(i).getCy();
            int p = arrayList.get(i).getI();
            double distance = Math.sqrt(Math.pow(x - cx -90, 2) + Math.pow(y - cy-90 , 2));
            if (distance <= 90) {
                EventBus.getDefault().post(new StringModel(p));
                return true;
            }
        }
        return false;
    }
}

drawable资源如果没有的话。就用安卓小机器人代替吧。

Ps-画完这个动画以后。内存吃的可厉害了。点击跳转到第二页一直报错。报xml文件错误。所有的背景图片都加载不了。一加就报错。最后报内存溢出。后来我改了半天。怀疑是内存不够了。先不执行这个动画。后面果然正常了。解决办法是在清单文件中加入:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"

        //加入硬件加速,否则比较卡顿
        android:hardwareAccelerated="true"
        //申请大内存,否则一直报内存溢出
        android:largeHeap="true"
android:hardwareAccelerated="true"
android:largeHeap="true"

加入这两个标签就可以正常运行了。因为我们是做大屏幕。内存这个可以随便申请。这个屏幕就跑我这一个项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

留白的云

感谢鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值