欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android仿微信表情雨下落效果的实现方法

程序员文章站 2022-06-29 09:18:33
前言 众所周知,微信聊天中我们输入一些关键词会有表情雨下落,比如输入「生日快乐」「么么哒」会有相应的蛋糕、亲吻的表情雨下落,今天就来完成这个表情雨下落的效果。下面话不多说...

前言

众所周知,微信聊天中我们输入一些关键词会有表情雨下落,比如输入「生日快乐」「么么哒」会有相应的蛋糕、亲吻的表情雨下落,今天就来完成这个表情雨下落的效果。下面话不多说了,来一起看看详细的介绍吧

效果图

先来看下效果,真·狗头雨·落!

android仿微信表情雨下落效果的实现方法

实现代码

确认表情的模型,定义属性

public class itememoje {
 //坐标
 public int x;
 public int y;
 // 横向偏移
 public int offsetx;
 //纵向偏移
 public int offsety;
 //缩放
 public float scale;
 //图片资源
 public bitmap bitmap;
}

自定义rainview 表情下落视图,初始化变量。

public class rainview extends view {
 private paint paint;
 //图片处理
 private matrix matrix;
 private random random;
 //判断是否运行的,默认没有
 private boolean isrun;
 //表情包集合
 private list<itememoje> bitmaplist;
 //表情图片
 private int imgresid = r.mipmap.dog;

 public rainview(context context) {
 this(context, null);
 }

 public rainview(context context, @nullable attributeset attrs) {
 this(context, attrs, 0);
 }

 public rainview(context context, @nullable attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);
 init();
 }

 private void init() {
 paint = new paint();
 paint.setantialias(true);
 paint.setfilterbitmap(true);
 paint.setdither(true);
 matrix = new matrix();
 random = new random();
 bitmaplist = new arraylist<>();
 }
}

初始化表情雨数据,确认每个表情的起始位置,下落过程中横向、纵向的偏移,以及缩放大小。

private void initdata() {
 for (int i = 0; i < 20; i++) {
 itememoje itememoje = new itememoje();
 itememoje.bitmap = bitmapfactory.decoderesource(getresources(), imgresid);
 //起始横坐标在[100,getwidth()-100) 之间
 itememoje.x = random.nextint(getwidth() - 200) + 100;
 //起始纵坐标在(-getheight(),0] 之间,即一开始位于屏幕上方以外
 itememoje.y = -random.nextint(getheight());
 //横向偏移[-2,2) ,即左右摇摆区间
 itememoje.offsetx = random.nextint(4) - 2;
 //纵向固定下落12
 itememoje.offsety = 12;
 //缩放比例[0.8,1.2) 之间
 itememoje.scale = (float) (random.nextint(40) + 80) / 100f;
 bitmaplist.add(itememoje);
 }
}

下落过程通过 ondraw进行绘制,不断的计算横纵坐标,达到下落效果。

@override
protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 if (isrun) {
 //用于判断表情下落结束,结束即不再进行重绘
 boolean isinscreen = false;
 for (int i = 0; i < bitmaplist.size(); i++) {
  matrix.reset();
  //缩放
  matrix.setscale(bitmaplist.get(i).scale, bitmaplist.get(i).scale);
  //下落过程坐标
  bitmaplist.get(i).x = bitmaplist.get(i).x + bitmaplist.get(i).offsetx;
  bitmaplist.get(i).y = bitmaplist.get(i).y + bitmaplist.get(i).offsety;
  if (bitmaplist.get(i).y <= getheight()) {//当表情仍在视图内,则继续重绘
  isinscreen = true;
  }
  //位移
  matrix.posttranslate(bitmaplist.get(i).x, bitmaplist.get(i).y);
  canvas.drawbitmap(bitmaplist.get(i).bitmap, matrix, paint);
 }
 if (isinscreen) {
  postinvalidate();
 }else {
  release();
 }
 }
}

/**
 *释放资源
 */
private void release(){
 if(bitmaplist != null && bitmaplist.size()>0){
 for(itememoje itememoje : bitmaplist){
  if(!itememoje.bitmap.isrecycled()){
  itememoje.bitmap.recycle();
  }
 }
 bitmaplist.clear();
 }
}

提供start() 方法触发。

public void start(boolean isrun) {
 this.isrun = isrun;
 initdata();
 postinvalidate();
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <com.rain.rainview
 android:id="@+id/testview"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

 <button
 android:id="@+id/btn_dog"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignparentbottom="true"
 android:text="真·狗头雨·落!" />

 <button
 android:id="@+id/btn_cake"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignparentbottom="true"
 android:layout_marginleft="10dp"
 android:layout_torightof="@+id/btn_dog"
 android:text="蛋糕雨" />

</relativelayout>

activity 点击事件触发

btncake.setonclicklistener(new view.onclicklistener() {
 @override
 public void onclick(view v) {
 //蛋糕图片
 rainview.setimgresid(r.mipmap.cake);
 rainview.start(true);
 }
});
btndog.setonclicklistener(new view.onclicklistener() {
 @override
 public void onclick(view v) {
 //狗头图片
 rainview.setimgresid(r.mipmap.dog);
 rainview.start(true);
 }
});

github地址: ()

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。