Android之蚂蚁森林能量水滴效果
创始人
2024-05-03 14:31:28
0

最近公司有个需求,需要一个类似于蚂蚁森林能量水滴浮动效果,所以有了这篇文章,目前在项目里,没时间提出来做demo,有代码欠缺的地方欢迎指出,一定补上。


文章目录

  • 一:效果图
  • 二:具体实现
    • 1.自定义圆球WaterView
    • 2.动态随机添加小球WaterFlake
    • 3:item布局(图片就是效果图的背景)
    • 4:xml布局
    • 5:activity使用
    • 6:Javabean(WaterModel)
  • 最后


一:效果图

第一张是蚂蚁效果图,第二张是项目里的效果图,换一下图片和设置一下文字颜色即可
在这里插入图片描述

Android雪花飘落效果以及仿蚂蚁森林能量水滴浮动效果

二:具体实现

1.自定义圆球WaterView

package com.mago.sports.utils;/*** Created by :caoliulang* ❤* Creation time :2022/8/31* ❤* Function :自定义仿支付宝蚂蚁森林水滴View*/
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;public class WaterView extends View {private Paint paint;private ObjectAnimator mAnimator;/*** 文字颜色*/private int textColor = Color.parseColor("#69c78e");/*** 水滴填充颜色*/private int waterColor = Color.parseColor("#c3f593");/*** 球描边颜色*/private int storkeColor = Color.parseColor("#69c78e");/*** 描边线条宽度*/private float strokeWidth = 0.5f;/*** 文字字体大小*/private float textSize = 36;/*** 水滴球半径*/private int mRadius = 30;/*** 圆球文字内容*/private String textContent="";public WaterView(Context context,String textContent) {super(context);this.textContent=textContent;init();}public WaterView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public WaterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {paint = new Paint();paint.setAntiAlias(true);}@Overridepublic void draw(Canvas canvas) {super.draw(canvas);drawCircleView(canvas);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);setMeasuredDimension(Utils.dp2px(getContext(), (int) (2 * (mRadius+strokeWidth))),Utils.dp2px(getContext(), (int) (2 * (mRadius+strokeWidth))));}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);Log.i("====》WaterView X",getX()+"==");Log.i("====》WaterView Y",getY()+"==");}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();start();}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();stop();}@Overrideprotected void onVisibilityChanged(@NonNull View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);if (visibility == VISIBLE) {start();} else {stop();}}private void drawCircleView(Canvas canvas){//圆球paint.setColor(waterColor);paint.setStyle(Paint.Style.FILL);canvas.drawCircle(Utils.dp2px(getContext(), mRadius), Utils.dp2px(getContext(), mRadius), Utils.dp2px(getContext(), mRadius), paint);//描边paint.setColor(storkeColor);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(Utils.dp2px(getContext(), (int) strokeWidth));canvas.drawCircle(Utils.dp2px(getContext(), mRadius), Utils.dp2px(getContext(), mRadius), Utils.dp2px(getContext(), (int) (mRadius+strokeWidth)) , paint);//圆球文字paint.setTextSize(textSize);paint.setColor(textColor);paint.setStyle(Paint.Style.FILL);drawVerticalText(canvas, Utils.dp2px(getContext(), mRadius), Utils.dp2px(getContext(), mRadius), textContent);}private void drawVerticalText(Canvas canvas, float centerX, float centerY, String text) {Paint.FontMetrics fontMetrics = paint.getFontMetrics();float baseLine = -(fontMetrics.ascent + fontMetrics.descent) / 2;float textWidth = paint.measureText(text);float startX = centerX - textWidth / 2;float endY = centerY + baseLine;canvas.drawText(text, startX, endY, paint);}public void start() {if (mAnimator == null) {mAnimator = ObjectAnimator.ofFloat(this, "translationY", -6.0f, 6.0f, -6.0f);mAnimator.setDuration(3500);mAnimator.setInterpolator(new LinearInterpolator());mAnimator.setRepeatMode(ValueAnimator.RESTART);mAnimator.setRepeatCount(ValueAnimator.INFINITE);mAnimator.start();} else if (!mAnimator.isStarted()) {mAnimator.start();}}public void stop() {if (mAnimator != null) {mAnimator.cancel();mAnimator = null;}}}

2.动态随机添加小球WaterFlake

package com.mago.sports.utils;/*** Created by :caoliulang* ❤* Creation time :2022/8/31* ❤* Function :支付宝蚂蚁森林水滴能量*/import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;import com.mago.sports.R;
import com.mago.sports.model.WaterModel;import java.util.Arrays;
import java.util.List;
import java.util.Random;public class WaterFlake extends FrameLayout {private static final int WHAT_ADD_PROGRESS = 1;private OnWaterItemListener mOnWaterItemListener;/*** 小树坐标X*/private float treeCenterX = 0;/*** 小树坐标Y*/private float treeCenterY = 0;/*** 是否正在收集能量*/private boolean isCollect = false;/*** view变化的y抖动范围*/private static final int CHANGE_RANGE = 10;/*** 控制抖动动画执行的快慢*/public static final int PROGRESS_DELAY_MILLIS = 12;/*** 控制水滴动画的偏移量*/private List mOffsets = Arrays.asList(5.0f, 4.5f, 4.8f, 5.5f, 5.8f, 6.0f, 6.5f);private Random mRandom = new Random();private float mWidth, mHeight;private LayoutInflater mLayoutInflater;public WaterFlake(@NonNull Context context) {this(context, null);}public WaterFlake(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public WaterFlake(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mLayoutInflater = LayoutInflater.from(getContext());}@Overridepublic boolean performClick() {return super.performClick();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mWidth = w;mHeight = h;}/*** 设置小球数据,根据数据集合创建小球数量** @param modelList 数据集合*/public void setModelList(final List modelList, float treeCenterX, float treeCenterY) {if (modelList == null || modelList.isEmpty()) {return;}this.treeCenterX = treeCenterX;this.treeCenterY = treeCenterY;removeAllViews();post(new Runnable() {@Overridepublic void run() {addWaterView(modelList);}});}/*** 设置小球数据,根据数据集合创建小球数量** @param modelList 数据集合*/public void setModelList(final List modelList, View view) {if (modelList == null || modelList.isEmpty()) {return;}this.treeCenterX = view.getX();this.treeCenterY = view.getY();removeAllViews();post(new Runnable() {@Overridepublic void run() {addWaterView(modelList);}});}private void addWaterView(List modelList) {int[] xRandom = randomCommon(1, 1, modelList.size());int[] yRandom = randomCommon(1, 1, modelList.size());if (xRandom == null || yRandom == null) {return;}for (int i = 0; i < modelList.size(); i++) {WaterModel waterModel = modelList.get(i);final View view = mLayoutInflater.inflate(R.layout.water_item1, this, false);TextView text_lk = view.findViewById(R.id.text_lk);text_lk.setText("LK:"+modelList.get(i).getContent());view.setX((float) ((mWidth * xRandom[i] * 0.11)));view.setY((float) ((mHeight * yRandom[i] * 0.08)));view.setTag(waterModel);view.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Object tag = v.getTag();if (tag instanceof WaterModel) {if (mOnWaterItemListener != null) {mOnWaterItemListener.onItemClick((WaterModel) tag);collectAnimator(view);}}}});view.setTag(R.string.isUp, mRandom.nextBoolean());setOffset(view);addView(view);addShowViewAnimation(view);start(view);}}/*** 设置小球点击事件** @param onWaterItemListener*/public void setOnWaterItemListener(OnWaterItemListener onWaterItemListener) {
//        mOnWaterItemListener = onWaterItemListener;}public interface OnWaterItemListener {void onItemClick(WaterModel waterModel);}private void collectAnimator(final View view) {if (isCollect) {return;}isCollect = true;ObjectAnimator translatAnimatorY = ObjectAnimator.ofFloat(view, "translationY", getTreeCenterY());translatAnimatorY.start();ObjectAnimator translatAnimatorX = ObjectAnimator.ofFloat(view, "translationX", getTreeCenterX());translatAnimatorX.start();ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);alphaAnimator.start();AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(translatAnimatorY).with(translatAnimatorX).with(alphaAnimator);animatorSet.setDuration(3000);animatorSet.start();animatorSet.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {removeView(view);isCollect = false;}});}public void start(View view) {boolean isUp = (boolean) view.getTag(R.string.isUp);float offset = (float) view.getTag(R.string.offset);ObjectAnimator mAnimator = null;if (isUp) {mAnimator = ObjectAnimator.ofFloat(view, "translationY", view.getY() - offset, view.getY() + offset, view.getY() - offset);} else {mAnimator = ObjectAnimator.ofFloat(view, "translationY", view.getY() + offset, view.getY() - offset, view.getY() + offset);}mAnimator.setDuration(1800);mAnimator.setInterpolator(new LinearInterpolator());mAnimator.setRepeatMode(ValueAnimator.RESTART);mAnimator.setRepeatCount(ValueAnimator.INFINITE);mAnimator.start();}/*** 添加显示动画** @param view*/private void addShowViewAnimation(View view) {view.setAlpha(0);view.setScaleX(0);view.setScaleY(0);view.animate().alpha(1).scaleX(1).scaleY(1).setDuration(500).start();}/*** 随机指定范围内N个不重复的数* 最简单最基本的方法** @param min 指定范围最小值* @param max 指定范围最大值* @param n   随机数个数*/public static int[] randomCommon(int min, int max, int n) {if (n > (max - min + 1) || max < min) {return null;}int[] result = new int[n];int count = 0;while (count < n) {int num = (int) ((Math.random() * (max - min)) + min);boolean flag = true;for (int j = 0; j < n; j++) {if (num == result[j]) {flag = false;break;}}if (flag) {result[count] = num;count++;}}return result;}public float getTreeCenterX() {return treeCenterX;}public float getTreeCenterY() {return treeCenterY;}/*** 设置View的offset** @param view*/private void setOffset(View view) {float offset = mOffsets.get(mRandom.nextInt(mOffsets.size()));view.setTag(R.string.offset, offset);}}

3:item布局(图片就是效果图的背景)




4:xml布局

根据公司需求所以是40dp,放了三个WaterFlake,你们可以一个WaterFlake铺满即可

 

5:activity使用

1:变量

private WaterFlake mWaterFlake;//能量浮动

2:实例化

 mWaterFlake = findViewById(R.id.mWaterFlake);

3:点击事件

 mWaterFlake.setOnWaterItemListener(new WaterFlake.OnWaterItemListener() {@Overridepublic void onItemClick(WaterModel pos) {}});

4:添加数据

 //此处目前写死坐标,后期可以获取小树的坐标添加进去mWaterFlake.setModelList(mModelList, text_start);

6:Javabean(WaterModel)

这里是一个数组,多个能量直接循环添加进去就行了

package com.mago.sports.model;/*** Created by :caoliulang* ❤* Creation time :2022/8/31* ❤* Function :*/
public class WaterModel {private String content;public WaterModel(String content) {this.content = content;}public String getContent() {return content;}
}

最后

有不足的地方欢迎指出,欢迎讨论!

相关内容

热门资讯

开源电脑安卓系统排行,探索自由... 亲爱的电脑爱好者们,你是否曾想过,在电脑的世界里,也能体验到安卓系统的便捷与乐趣?没错,这就是今天我...
如何清空相册安卓系统,轻松恢复... 手机里的相册是不是越来越满,看着那些堆积如山的照片,是不是有点头疼呢?别急,今天就来教你怎么在安卓系...
安卓系统要停止更新,拥抱新变革 你知道吗?最近有个大消息在安卓圈里炸开了锅!安卓系统,这个陪伴我们多年的老朋友,竟然要停止更新了!这...
安卓系统怎样强行关机,安卓系统... 手机突然卡壳了,是不是又想强行关机了?别急,今天就来教你安卓系统怎样强行关机,让你轻松应对各种突发状...
安卓系统如何删除桌面,轻松删除... 手机桌面乱糟糟的,是不是感觉像你的房间一样,东西堆得有点多?别急,今天就来教你怎么给安卓系统的桌面来...
安卓系统怎么发英语,Andro... 你有没有想过,在安卓系统上发送英语信息竟然也能变得如此简单有趣?没错,就是那种轻松自如,仿佛英语是你...
最早期的安卓系统,揭秘最早期安... 亲爱的读者,你是否曾好奇过,那个陪伴我们手机成长的安卓系统,它的起源究竟是怎样的呢?今天,就让我们一...
安卓双系统添加应用,轻松实现多... 你有没有想过,你的安卓手机里可以同时运行两个系统呢?听起来是不是很酷?想象一边是熟悉的安卓系统,一边...
pipo安卓进系统慢,探究pi... 最近是不是发现你的Pipo安卓系统更新或者运行起来特别慢?别急,今天就来给你好好分析分析这个问题,让...
怎样使用安卓手机系统,安卓手机... 你有没有发现,安卓手机已经成为我们生活中不可或缺的一部分呢?从早晨闹钟响起,到晚上睡前刷剧,安卓手机...
双系统安卓安装caj,轻松实现... 你有没有想过,你的安卓手机里装上双系统,是不是就能同时享受安卓和Windows系统的乐趣呢?没错,这...
安卓使用ios系统教程,安卓用... 你是不是也和我一样,对安卓手机上的iOS系统充满了好奇?想要体验一下苹果的优雅和流畅?别急,今天我就...
安卓系统gps快速定位,畅享便... 你有没有遇到过这样的情况:手机里装了各种地图导航软件,但每次出门前都要等上好几分钟才能定位成功,急得...
安卓手机系统更新原理,原理与流... 你有没有发现,你的安卓手机最近是不是总在提醒你更新系统呢?别急,别急,让我来给你揭秘一下安卓手机系统...
安卓系统通知管理,全面解析与优... 你有没有发现,手机里的通知就像是一群调皮的小精灵,时不时地跳出来和你互动?没错,说的就是安卓系统的通...
安卓系统手机哪买,揭秘哪里购买... 你有没有想过,拥有一部安卓系统手机是多么酷的事情呢?想象你可以自由安装各种应用,不受限制地探索各种功...
安卓系统 ipv4,基于安卓系... 你知道吗?在智能手机的世界里,有一个系统可是无人不知、无人不晓,那就是安卓系统。而在这个庞大的安卓家...
目前安卓是什么系统,探索安卓系... 亲爱的读者,你是否曾好奇过,如今安卓系统究竟是什么模样?在这个科技飞速发展的时代,操作系统如同人体的...
安卓6.0系统比5.0,从5.... 你有没有发现,自从手机更新了安卓6.0系统,感觉整个人都清爽了不少呢?没错,今天咱们就来聊聊这个话题...
安卓2.36系统升级,功能革新... 你知道吗?最近安卓系统又来了一次大变身,那就是安卓2.36系统升级!这可不是一个小打小闹的更新,而是...