本文介绍了AndroID实现红包雨动画效果,分享给大家,希望对大家有帮助
红包雨
关于实现上面红包雨效果步骤如下:
1.创建一个红包实体类
public class RedPacket { public float x,y; public float rotation; public float speed; public float rotationSpeed; public int wIDth,height; public Bitmap bitmap; public int money; public boolean isRealRed; public RedPacket(Context context,Bitmap originalBitmap,int speed,float maxSize,float minSize,int vIEwWIDth) { //获取一个显示红包大小的倍数 double wIDthRandom = Math.random(); if (wIDthRandom < minSize || wIDthRandom > maxSize) { wIDthRandom = maxSize; } //红包的宽度 wIDth = (int) (originalBitmap.getWIDth() * wIDthRandom); //红包的高度 height = wIDth * originalBitmap.getHeight() / originalBitmap.getWIDth(); int mWIDth = (vIEwWIDth == 0) ? context.getResources().getdisplayMetrics().wIDthPixels : vIEwWIDth; //生成红包bitmap bitmap = Bitmap.createScaledBitmap(originalBitmap,wIDth,height,true); originalBitmap.recycle(); Random random = new Random(); //红包起始位置x:[0,mWIDth-wIDth] int rx = random.nextInt(mWIDth) - wIDth; x = rx <= 0 ? 0 : rx; //红包起始位置y y = -height; //初始化该红包的下落速度 this.speed = speed + (float) Math.random() * 1000; //初始化该红包的初始旋转角度 rotation = (float) Math.random() * 180 - 90; //初始化该红包的旋转速度 rotationSpeed = (float) Math.random() * 90 - 45; //初始化是否为中奖红包 isRealRed = isRealRedPacket(); } /** * 判断当前点是否包含在区域内 */ public boolean isContains(float x,float y) { //稍微扩大下点击的区域 return this.x-50 < x && this.x +50 + wIDth > x && this.y-50 < y && this.y+50 + height > y; } /** * 随机 是否为中奖红包 */ public boolean isRealRedPacket() { Random random = new Random(); int num = random.nextInt(10) + 1; //如果[1,10]随机出的数字是2的倍数 为中奖红包 if (num % 2 == 0) { money = num*2;//中奖金额 return true; } return false; } /** * 回收图片 */ public voID recycle() { if (bitmap!= null && !bitmap.isRecycled()){ bitmap.recycle(); } }}
上面就红包实体类的源码,重点就是在创建红包实体的时候,初始化红包相关的值,如生成红包图片,图片的宽高,红包初始位置,下落速度等。比较简单。
2.自定义红包雨vIEw
vIEw初始化
public RedPacketTest(Context context,@Nullable AttributeSet attrs) { super(context,attrs); final TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.RedPacketStyle); //获取xml中配置的vIEw的style属性,如下落红包数量,下落的基础速度,以及红包图片的最大最小范围 count = typedArray.getInt(R.styleable.RedPacketStyle_count,20); speed = typedArray.getInt(R.styleable.RedPacketStyle_speed,20); minSize = typedArray.getfloat(R.styleable.RedPacketStyle_min_size,0.5f); maxSize = typedArray.getfloat(R.styleable.RedPacketStyle_max_size,1.2f); typedArray.recycle(); init(); } /** * 初始化 */ private voID init() { //初始化画笔 paint = new Paint(); paint.setFilterBitmap(true); paint.setDither(true); paint.setAntiAlias(true); //创建一个属性动画,通过属性动画来控制刷新红包下落的位置 animator = ValueAnimator.offloat(0,1); //绘制vIEw开启硬件加速 setLayerType(VIEw.LAYER_TYPE_HARDWARE,null); //初始化属性动画 initAnimator(); } private voID initAnimator() { //每次动画更新的时候,更新红包下落的坐标值 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @OverrIDe public voID onAnimationUpdate(ValueAnimator animation) { long NowTime = System.currentTimeMillis(); //获取两次动画更新之间的时间,以此来计算下落的高度 float secs = (float) (NowTime - prevTime) / 1000f; prevTime = NowTime; for (int i = 0; i < redpacketList.size(); ++i) { RedPacket redPacket = redpacketList.get(i); //更新红包的下落的位置y redPacket.y += (redPacket.speed * secs); //如果y坐标大于vIEw的高度 说明划出屏幕,y重新设置起始位置,以及中奖属性 if (redPacket.y > getHeight()) { redPacket.y = 0 - redPacket.height; redPacket.isRealRed = redPacket.isRealRedPacket(); } //更新红包的旋转的角度 redPacket.rotation = redPacket.rotation + (redPacket.rotationSpeed * secs); } //重绘 invalIDate(); } }); //属性动画无限循环 animator.setRepeatCount(ValueAnimator.INFINITE); //属性值线性变换 animator.setInterpolator(new linearInterpolator()); animator.setDuration(0); }
vIEw绘制
@OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { super.onMeasure(wIDthMeasureSpec,heightmeasureSpec); //获取自定义view的宽度 mWIDth = getMeasureDWIDth(); } @OverrIDe protected voID onDraw(final Canvas canvas) { //遍历红包数组,绘制红包 for (int i = 0; i < redpacketList.size(); i++) { RedPacket redPacket = redpacketList.get(i); //将红包旋转redPacket.rotation角度后 移动到(redPacket.x,redPacket.y)进行绘制红包 Matrix m = new Matrix(); m.setTranslate(-redPacket.wIDth / 2,-redPacket.height / 2); m.postRotate(redPacket.rotation); m.postTranslate(redPacket.wIDth / 2 + redPacket.x,redPacket.height / 2 + redPacket.y); //绘制红包 canvas.drawBitmap(redPacket.bitmap,m,paint); } }
红包雨动画开始结束
/** *停止动画 */ public voID stopRainNow() { //清空红包数据 clear(); //重绘 invalIDate(); //动画取消 animator.cancel(); } /** * 开始动画 */ public voID startRain() { //清空红包数据 clear(); //添加红包 setRedpacketCount(count); prevTime = System.currentTimeMillis(); //动画开始 animator.start(); } public voID setRedpacketCount(int count) { if (mimgIDs == null || mimgIDs.length == 0) return; for (int i = 0; i < count; ++i) { //获取红包原始图片 Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),mimgIDs[0]); //生成红包实体类 RedPacket redPacket = new RedPacket(getContext(),originalBitmap,speed,maxSize,minSize,mWIDth); //添加进入红包数组 redpacketList.add(redPacket); } } /** * 暂停红包雨 */ public voID pauseRain() { animator.cancel(); } /** * 重新开始 */ public voID restartRain() { animator.start(); } /** * 清空红包数据,并回收红包中的bitmap */ private voID clear() { for (RedPacket redPacket :redpacketList) { redPacket.recycle(); } redpacketList.clear(); }
红包点击事件
@OverrIDe public boolean ontouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: //根据点击的坐标点,判断是否点击在红包的区域 RedPacket redPacket = isRedPacketClick(motionEvent.getX(),motionEvent.getY()); if (redPacket != null) { //如果点击在红包上,重新设置起始位置,以及中奖属性 redPacket.y = 0 - redPacket.height; redPacket.isRealRed = redPacket.isRealRedPacket(); if (onRedPacketClickListener != null) { onRedPacketClickListener.onRedPacketClickListener(redPacket); } } break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: break; } return true; } //根据点击坐标点,遍历红包数组,看是否点击在红包上 private RedPacket isRedPacketClick(float x,float y) { for (int i = redpacketList.size() - 1; i >= 0; i --) { if (redpacketList.get(i).isContains(x,y)) { return redpacketList.get(i); } } return null; }
关于自定义红包雨vIEw的主要代码以及分析基本完成了。下面是自定义view的使用。
3.自定义view的使用
红包雨Activity
public class RedPacketActivity extends AppCompatActivity implements VIEw.OnClickListener { private RedPacketTest redRainVIEw1; private button start,stop; private TextVIEw money; private int totalmoney = 0; AlertDialog.Builder ab; @OverrIDe protected voID onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.red_rain); ab = new AlertDialog.Builder(RedPacketActivity.this); start = (button) findVIEwByID(R.ID.start); stop = (button) findVIEwByID(R.ID.stop); money = (TextVIEw) findVIEwByID(R.ID.money); redRainVIEw1 = (RedPacketTest) findVIEwByID(R.ID.red_packets_vIEw1); start.setonClickListener(this); stop.setonClickListener(this); } @OverrIDe public voID onClick(VIEw v) { if (v.getID() == R.ID.start) { startRedRain(); } else if (v.getID() == R.ID.stop) { stopRedRain(); } } /** * 开始下红包雨 */ private voID startRedRain() { redRainVIEw1.startRain(); redRainVIEw1.setonRedPacketClickListener(new RedPacketTest.OnRedPacketClickListener() { @OverrIDe public voID onRedPacketClickListener(RedPacket redPacket) { redRainVIEw1.pauseRain(); ab.setCancelable(false); ab.setTitle("红包提醒"); ab.setNegativebutton("继续抢红包",new DialogInterface.OnClickListener() { @OverrIDe public voID onClick(DialogInterface dialog,int which) { redRainVIEw1.restartRain(); } }); if (redPacket.isRealRed) { ab.setMessage("恭喜你,抢到了" + redPacket.money + "元!"); totalmoney += redPacket.money; money.setText("中奖金额: " + totalmoney); } else { ab.setMessage("很遗憾,下次继续努力!"); } redRainVIEw1.post(new Runnable() { @OverrIDe public voID run() { ab.show(); } }); } }); } /** * 停止下红包雨 */ private voID stopRedRain() { totalmoney = 0;//金额清零 redRainVIEw1.stopRainNow(); }
红包雨Activity的xml
<?xml version="1.0" enCoding="utf-8"?><relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:background="#80000000"> <ImageVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:scaleType="fitXY" androID:src="@drawable/red_packets_bg" /> <button androID:ID="@+ID/start" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="开始" /> <button androID:ID="@+ID/stop" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_alignParentRight="true" androID:text="结束" /> <TextVIEw androID:ID="@+ID/money" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:text="中奖金额:" androID:textSize="18sp" androID:layout_margintop="10dp" /> <com.example.test.redpacketrain.RedPacketTest androID:ID="@+ID/red_packets_vIEw1" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" app:count="20" app:max_size="0.8" app:min_size="0.6" app:speed="500" /></relativeLayout>
自定义view的styleable
<resources> <declare-styleable name="RedPacketStyle"> <attr name="count" format="integer" /> <attr name="speed" format="integer" /> <attr name="max_size" format="float" /> <attr name="min_size" format="float" /> </declare-styleable></resources>
完整的自定义view代码
public class RedPacketTest extends VIEw { private int[] mimgIDs = new int[]{ R.drawable.red_packets_icon };//红包图片 private int count;//红包数量 private int speed;//下落速度 private float maxSize;//红包大小的范围 private float minSize;//红包大小的范围 private int mWIDth;//vIEw宽度 private ValueAnimator animator;//属性动画,用该动画来不断改变红包下落的坐标值 private Paint paint;//画笔 private long prevTime; private ArrayList<RedPacket> redpacketList = new ArrayList<>();//红包数组 public RedPacketTest(Context context) { super(context); init(); } public RedPacketTest(Context context,R.styleable.RedPacketStyle); count = typedArray.getInt(R.styleable.RedPacketStyle_count,1.2f); typedArray.recycle(); init(); } /** * 初始化 */ private voID init() { paint = new Paint(); paint.setFilterBitmap(true); paint.setDither(true); paint.setAntiAlias(true); animator = ValueAnimator.offloat(0,1); setLayerType(VIEw.LAYER_TYPE_HARDWARE,null); initAnimator(); } private voID initAnimator() { //每次动画更新的时候,更新红包下落的坐标值 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @OverrIDe public voID onAnimationUpdate(ValueAnimator animation) { long NowTime = System.currentTimeMillis(); float secs = (float) (NowTime - prevTime) / 1000f; prevTime = NowTime; for (int i = 0; i < redpacketList.size(); ++i) { RedPacket redPacket = redpacketList.get(i); //更新红包的下落的位置y redPacket.y += (redPacket.speed * secs); //如果y坐标大于vIEw的高度 说明划出屏幕,y重新设置起始位置,以及中奖属性 if (redPacket.y > getHeight()) { redPacket.y = 0 - redPacket.height; redPacket.isRealRed = redPacket.isRealRedPacket(); } //更新红包的旋转的角度 redPacket.rotation = redPacket.rotation + (redPacket.rotationSpeed * secs); } invalIDate(); } }); //属性动画无限循环 animator.setRepeatCount(ValueAnimator.INFINITE); //属性值线性变换 animator.setInterpolator(new linearInterpolator()); animator.setDuration(0); } /** *停止动画 */ public voID stopRainNow() { //清空红包数据 clear(); //重绘 invalIDate(); //动画取消 animator.cancel(); } /** * 开始动画 */ public voID startRain() { //清空红包数据 clear(); //添加红包 setRedpacketCount(count); prevTime = System.currentTimeMillis(); //动画开始 animator.start(); } public voID setRedpacketCount(int count) { if (mimgIDs == null || mimgIDs.length == 0) return; for (int i = 0; i < count; ++i) { //获取红包原始图片 Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),mWIDth); //添加进入红包数组 redpacketList.add(redPacket); } } /** * 暂停红包雨 */ public voID pauseRain() { animator.cancel(); } /** * 重新开始 */ public voID restartRain() { animator.start(); } /** * 清空红包数据,并回收红包中的bitmap */ private voID clear() { for (RedPacket redPacket :redpacketList) { redPacket.recycle(); } redpacketList.clear(); } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec,paint); } } @OverrIDe public boolean ontouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: //根据点击的坐标点,判断是否点击在红包的区域 RedPacket redPacket = isRedPacketClick(motionEvent.getX(),y)) { return redpacketList.get(i); } } return null; } public interface OnRedPacketClickListener { voID onRedPacketClickListener(RedPacket redPacket); } private OnRedPacketClickListener onRedPacketClickListener; public voID setonRedPacketClickListener(OnRedPacketClickListener onRedPacketClickListener) { this.onRedPacketClickListener = onRedPacketClickListener; }}
最后
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
总结以上是内存溢出为你收集整理的Android实现红包雨动画效果全部内容,希望文章能够帮你解决Android实现红包雨动画效果所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)