微信android客户端中的表情雨效果在聊天中生动活泼,具体会出现特殊效果的词有恭喜发财、年年有余、想你了、生日快乐、么么哒等等,随着节日来临会有更新词库及图片内容出现。具体效果如下图:

现就其实现过程进行一详细分析。

这个功能可以分为两步走:

第一步是取用服务器词库及表情图片,以及对聊天页面发送的文字的监听,这一点并没有什么要特别注意的,本文略过。

第二步也就是实现表情雨的关键,即UI的展示效果及其中涉及的一系列问题。下面做一简要分析及实现。

从微信表情雨的效果来看,是一张表情图icon以随机位置、随机速度、随机初始时间(皆在指定的范围内)从屏幕顶端向屏幕底端的平移运动,认清了这一点,实现起来逻辑就比较清晰了。按照这一目标,可以自定义一个EmotionsView如下,这里假设使用本地图片drawable/test_icon.png,并设置有20个表情。

public class EmotionsView extends View {    // 表情图片
Bitmap bitmap_emotion = null;    private boolean isEnd = true;    public boolean isEnd() {
return isEnd;
}    public void setEnd(boolean isEnd) {
this.isEnd = isEnd;
}    private final Paint mPaint = new Paint();    private static final Random RNG = new Random();    private Coordinate[] emotions = new Coordinate[20];    int view_height = 0;
int view_width = 0;    private int[] emotionX = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
private int[] emotionY = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
private int[] emotionZ = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};    public EmotionsView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}    public EmotionsView(Context context, AttributeSet attrs) {
super(context, attrs);    }    public void LoadEmotionImage() {
Resources r = this.getContext().getResources();
bitmap_emotion = ((BitmapDrawable) r.getDrawable(R.drawable.test_icon)).getBitmap();
}    public void LoadEmotionImage(int intDrawable) {
Resources r = this.getContext().getResources();
bitmap_emotion = ((BitmapDrawable) r.getDrawable(intDrawable)).getBitmap();
}    public void setView(int height, int width) {
view_height = height - 100;
view_width = width - 50;    }    public void clearAllEmotions() {
emotionX = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
emotionY = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
emotionZ = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};    }    /**
* 随机生成位置
*/
public void addRandomEmotion() {
calculateNextCoordinate();
for (int i = 0; i < 20; i++) {
if (emotions[i] == null) {
emotions[i] = new Coordinate(emotionX[i], emotionY[i]);
} else {
emotions[i].setXY(emotionX[i], emotionY[i]);
}
if (emotionY[i] >= view_height) {
emotions[i] = null;
}
}
}    private void calculateNextCoordinate() {
for (int i = 0; i < 20; i++) {
if (emotionX[i] == 0) {
emotionY[i] = RNG.nextInt(1000) - 1000;
emotionX[i] = RNG.nextInt(view_width - 1) + 1;
emotionZ[i] = RNG.nextInt(20) + 10;
}
else {
emotionY[i] += emotionZ[i];
}
}
}    private class Coordinate {
public int x;
public int y;        public Coordinate(int newX, int newY) {
x = newX;
y = newY;
}        public boolean equals(Coordinate other) {
if (x == other.x && y == other.y) {
return true;
}
return false;
}        @Override
public String toString() {
return "Coordinate: [" + x + "," + y + "]";
}        public void setXY(int x, int y) {
this.x = x;
this.y = y;
}
}    @Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isEnd) {
return;
}
boolean temp = true;
for (int x = 0; x < 20; x += 1) {
if (emotions[x] != null && bitmap_emotion != null && !bitmap_emotion.isRecycled()) {
canvas.drawBitmap(bitmap_emotion, ((float) emotions[x].x),
((float) emotions[x].y), mPaint);
temp = false;
}
}
if (temp) {
isEnd = true;
}
}}

并自定义BackgroundView如下:

public class BackgroundView extends View {    private static final String TAG = "BackgroundView";
// 屏幕的高度和宽度
int view_height = 0;
int view_width = 0;
Bitmap bmp = null;    /**
* 构造器
*/
public BackgroundView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}    public BackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);    }    /**
* 设置当前窗体的实际高度和宽度
*/
public void SetView(int height, int width) {
view_height = height;
view_width = width;
}    public void SetBitmap(Bitmap bitmap) {
bmp = bitmap;
}    @SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//        MyLog.d(TAG, view_width + " " + view_height);
if (bmp == null) {
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.wish_background);
}
Rect src = new Rect();// 图片
Rect dst = new Rect();// 屏幕位置及尺寸
// src 这个是表示绘画图片的大小
src.left = 0; // 0,0
src.top = 0;
src.right = bmp.getWidth();// mBitDestTop.getWidth();,这个是桌面图的宽度,
src.bottom = bmp.getHeight();// mBitDestTop.getHeight()/2;//
// 这个是桌面图的高度的一半
// 下面的 dst 是表示 绘画这个图片的位置
dst.left = 0; // miDTX,//这个是可以改变的,也就是绘图的起点X位置
dst.top = 0; // mBitQQ.getHeight();//这个是QQ图片的高度。 也就相当于 桌面图片绘画起点的Y坐标
dst.right = view_width; // miDTX + mBitDestTop.getWidth();//
// 表示需绘画的图片的右上角
dst.bottom = view_height; // mBitQQ.getHeight() +
// mBitDestTop.getHeight();//表示需绘画的图片的右下角
canvas.drawBitmap(bmp, src, dst, null);// 这个方法 第一个参数是图片原来的大小,第二个参数是
// 绘画该图片需显示多少。也就是说你想绘画该图片的某一些地方,而不是全部图片,第三个参数表示该图片绘画的位置        src = null;
dst = null;
} 

在聊天页面中,编写表情雨动画函数showEmotionsView(),通过一个Handler实现表情动画。节选代码如下:

private RefreshHandler mRedrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (ev == null || ev.isEnd()) {
return;
}
ev.addRandomEmotion();            ev.invalidate();
sleep(50);
}        public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
public void update() {
ev.setEnd(false);
ev.clearAllEmotions();
ev.addRandomEmotion();
mRedrawHandler.removeMessages(0);
mRedrawHandler.sleep(200);
} private void showEmotionsView() {
// 获得表情雨视图,加载icon到内存(在布局文件中置入自定义EmotionsView)
ev = (EmotionsView) findViewById(R.id.emotion_view);        // 此处可实现表情图片的更替,具体判断来自发送的文本内容
int intDrawable = R.drawable.test_icon2;
ev.LoadEmotionImage(intDrawable);
BV.invalidate();
ev.setVisibility(View.VISIBLE);        // 获取当前屏幕的高和宽
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
ev.setView(dm.heightPixels, dm.widthPixels);
update();
}

以该思路实现的表情雨动画在各版本Android中均测试通过,由于采用了读取手机屏幕宽、高,利用随机数计算的办法,妥善解决了屏幕适配的问题,如将问题引申,如表情随着运动有大小闪烁变化,或运动轨迹不仅是y轴竖直平移,均可在此基础上加以改进,给聊天页面增添生动的效果。

微信Android客户端中表情雨效果的实现相关推荐

  1. 微信Android客户端的ANR监控方案

    微信Android客户端的ANR监控方案 微信公众号,WeMobileDev 2021年7月19日发布的 微信Android客户端的ANR监控方案 该方案的所有代码已经在Matrix(https:// ...

  2. 微信Android客户端的卡顿监控方案

    2021.8.1  Matrix 2.0 TraceCanary新增了以下功能 微信Android客户端的卡顿监控方案 https://mp.weixin.qq.com/s/3dubi2GVW_rVF ...

  3. 微信Android客户端架构演进之路

    去年7月,笔者在InfoQ举办的ArchSummit深圳2014的架构师峰会上,分享了微信Android客户端的架构演进史.可以说,这是一个典型的Android应用在从小到大的成长过程中的" ...

  4. 微信Android客户端架构演进及其对开发流程的影响

    微信Android客户端架构演进及其对开发流程的影响 http://www.infoq.com/cn/presentations/android-client-architecture-evoluti ...

  5. android 判断安装微信,Android开发中判断手机是否安装了QQ或者微信

    下面一段代码给大家分享了android中判断手机是否安装了qq或者微信,代码简单易懂,非常不错,具有参考借鉴价值,需要的的朋友参考下吧 public static boolean isWeixinAv ...

  6. 如何在android客户端中做到自动检查数据更新?,UpdateHelper

    软件简介 UpdateHelper 是一个为了简化Android App的迭代升级开发的Android Library,任何一个项目只要引入这个library便集成了在线检查新版本的功能以及下载APK ...

  7. Android直播中弹幕效果实现

    在B站或者其他视频网站看视频时,常常会打开弹幕效果,边看节目边看大家的吐槽.弹幕看起来很有意思,今天我们就来实现一个简单的弹幕效果. 从直观上,弹幕效果就是在一个ViewGroup上增加一些View, ...

  8. 微信 Android 视频编码爬过的那些坑

    [编者按]Android 视频相关的开发,大概一直是整个 Android 生态.以及 Android API 中,最为分裂以及兼容性问题最为突出的一部分,本文从视频编码器的选择和如何对摄像头输出的 Y ...

  9. 微信android手机中点击大图片会自动放大图片

    自己使用的是微信Android客户端,使用img标签的src属性将图片设置好了以后,在微信中调试,点击图片竟然放大,自己没写放大图片的方法,也没有调用wx.previewImage()方法,最后查找, ...

最新文章

  1. html导入.md文件并渲染,vue 导入.md文件(markdown转HTML)
  2. java cookie的有效期_Java Web cookie的有效期
  3. 心电信号去噪(part4)--经验模态分解法(EMD)
  4. 最简单的c语言的编程题目,编程列入考题
  5. 知乎超高赞:都有哪些习惯值得长期坚持?
  6. true,false组合问题
  7. flutter 输入框限制输入 数字、小数
  8. java map hashtable_Java的HashMap和HashTable
  9. FIle类常用工具方法整理(持续更新)
  10. HTTP常见问题总结
  11. Python 爬虫---(3)Urllib库使用介绍
  12. python实现发送免费短信功能
  13. 其实,API 编程并不难!
  14. Android xml文件的序列化
  15. JAVA课程设计(小游戏贪吃蛇)完整源码附素材(三)
  16. oracle 触发器代码,Oracle触发器实例代码
  17. 微信公众号订阅号与微信服务号有什么不同
  18. TestCenter测试管理工具功能详解十五(T)
  19. 用 python 快速「卡通化」人物头像
  20. Win7 注册ocx控件 “DllRegisterServer的调用失败,错误代码为0x80040200 ”

热门文章

  1. 树莓派-- NOOBS安装
  2. H3C V7 旁挂防火墙静态路由引流
  3. 怎么让CAD文件中图像单独保存
  4. QT:QChart设置
  5. 计算机是人类的好伴侣 作文,书是我们的好伴侣_我和书的故事作文
  6. 【机器学习知识整理二】处理分类数据、处理文本、处理日期和时间
  7. 随手记录,idea无法创建class,文件夹没有小圆点
  8. php中 r,PHP中转义字符 (n r)
  9. html5颜值测试小游戏,html5毫秒统计测试手指点击速度手机游戏
  10. (JAVA)支付宝小程序登录相关(authToken获取用户唯一userId、encryptedData解密手机号)