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;}
}

最后

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

相关内容

热门资讯

安卓系统自带的网页,功能与特色... 你有没有发现,每次打开安卓手机,那熟悉的系统界面里总有一个默默无闻的小家伙——安卓系统自带的网页浏览...
美咖云系统安卓版,开启智能生活... 你有没有发现,最近手机上多了一个叫“美咖云系统安卓版”的小家伙?它就像一个魔法师,轻轻一点,就能让你...
安卓系统推荐最好的手机,盘点性... 你有没有想过,拥有一部性能卓越的手机,就像是拥有了移动的宝藏库?在这个信息爆炸的时代,一部好手机不仅...
安卓11系统能精简吗,释放潜能 你有没有发现,随着手机越来越智能,系统也越来越庞大?安卓11系统,这个最新的操作系统,是不是也让你觉...
安卓自动重启系统软件,揭秘原因... 手机突然自动重启,是不是感觉整个人都不好了?别急,今天就来和你聊聊这个让人头疼的安卓自动重启系统软件...
苹果手机x刷安卓系统,探索安卓... 你有没有想过,你的苹果手机X竟然也能刷上安卓系统?是的,你没听错,就是那个一直以来都和我们苹果手机X...
安卓系统智商低吗,智商低下的真... 你有没有想过,为什么安卓系统的智商总被调侃得好像有点低呢?是不是觉得它总是慢吞吞的,有时候还犯点小错...
安卓系统手机联系人,揭秘你的社... 你有没有发现,手机里的联系人列表就像是一个小小的社交圈呢?里面藏着我们的亲朋好友、工作伙伴,甚至还有...
安卓系统免费铃声下载,打造个性... 手机里那首老掉牙的铃声是不是让你觉得有点out了呢?别急,今天就来给你支个招,让你轻松给安卓手机换上...
安卓系统用哪个桌面好,打造个性... 你有没有发现,手机桌面可是我们每天都要面对的“脸面”呢?换一个好看的桌面,心情都能跟着好起来。那么,...
虚拟大师是安卓10系统,功能与... 你知道吗?最近在手机圈里,有个新玩意儿引起了不小的轰动,那就是虚拟大师!而且,更让人惊喜的是,这个虚...
安卓系统与苹果优缺点,系统优缺... 说到手机操作系统,安卓和苹果绝对是两大巨头,它们各有各的特色,就像两道不同的美味佳肴,让人难以抉择。...
安卓win双系统主板,融合与创... 你有没有想过,一台电脑如果既能流畅运行安卓系统,又能轻松驾驭Windows系统,那该有多爽啊?没错,...
安卓系统可精简软件,轻松提升手... 你有没有发现,手机里的安卓系统越来越庞大,软件也越装越多,有时候感觉手机就像个“大肚子”,不仅运行速...
安卓系统基于linux的代码,... 你有没有想过,那个陪伴你每天刷抖音、玩游戏、办公的安卓系统,其实背后有着一套复杂的基于Linux的代...
苹果和安卓的拍照系统,谁更胜一... 你有没有发现,现在手机拍照已经成为我们生活中不可或缺的一部分呢?无论是记录生活的点滴,还是捕捉美丽的...
苹果和安卓系统不同吗,系统差异... 你有没有想过,为什么你的手机里装的是苹果的iOS系统,而朋友的手机却是安卓系统呢?这两种系统,看似都...
安卓系统有多少级,揭秘其多级架... 你有没有想过,那个陪伴我们日常生活的安卓系统,它其实有着丰富的层级结构呢?没错,就是那个让我们的手机...
华为鸿蒙系统与安卓的,技术融合... 你知道吗?最近科技圈可是炸开了锅,华为鸿蒙系统与安卓的较量成为了大家热议的话题。这不,今天我就来给你...
什么安卓手机是苹果系统,搭载苹... 你有没有想过,为什么有些人宁愿花大价钱买苹果手机,而有些人却对安卓手机情有独钟呢?其实,这个问题背后...