仿微信表情输入键盘(支持 Gif 表情图文混排 )
作者 | PandaQ404
地址 | http://www.jianshu.com/p/fddca2b0a26b
声明 | 本文是 PandaQ404 原创,已获授权发布,未经原作者允许请勿转载
简介
自定义的表情输入键盘在很多应用中都会有用到,譬如微信、QQ 等社交聊天软件中更是不可缺少的部分。本文将解析一下个人的自定义表情输入控件库 PandaEmoView 的实现和使用。
特点
支持 emoji 表情图片
支持 gif 动态表情输入显示
支持单张贴图表情(与微信收藏表情一致)
支持题图表情库的添加删除
效果图
快速使用
引入库
compile 'com.pandaq:PandaEmoView:1.0.0'
表情资源及配置文件
默认的 emoji 和 gif 表情以及他们的配置文件是放在开发包 assets 目录下的,若表情比较多比较大也可自行修改源码在 APP 启动时从服务器下载。
emoji 表情配置文件
非自定义 sticker 配置文件(自定义 sticker 是没有配置文件的)
具体使用规则
与表情输入控件相关的 EditText 必须使用 PandaEditText
PandaEditText 只是重写了 onKeyPreIme() 获取按返回键的通知,继承自 EditText 的控件可继承 PandaEditText 自定义
应用 Application 中进行全局参数配置
private void configPandaEmoView() { new PandaEmoManager.Builder() .with(getApplicationContext()) // 传递 Context .configFileName("emoji.xml")// 配置文件名称 .emoticonDir("face") // asset 下存放表情的目录路径(asset——> configFileName 之间的路径,结尾不带斜杠) .sourceDir("images") // 存放 emoji 表情资源文件夹路径(emoticonDir 图片资源之间的路径,结尾不带斜杠) .showAddTab(true)//tab栏是否显示添加按钮 .showStickers(true)//tab栏是否显示贴图切换按键 .showSetTab(true)//tab栏是否显示设置按钮 .defaultBounds(30)//emoji 表情显示出来的宽高 .cacheSize(1024)//加载资源到内存时 LruCache 缓存大小 .defaultTabIcon(R.drawable.ic_default)//emoji表情Tab栏图标 .emojiColumn(7)//单页显示表情的列数 .emojiRow(3)//单页显示表情的行数 .stickerRow(2)//单页显示贴图表情的行数 .stickerColumn(4)//单页显示贴图表情的列数 .maxCustomStickers(30)//允许添加的收藏表情数 .imageLoader(new IImageLoader() { @Override public void displayImage(String path, ImageView imageView) { // 加载贴图表情的图片加载接口 Picasso.with(getApplicationContext()) .load(path) .fit() .centerCrop() .into(imageView); } }) .build(); //构建 PandaEmoManager 单利 }
2.使用此控件的 Activity 在 manifest 文件中配置
// 这句是一定要加上的。android:windowSoftInputMode="adjustResize"
3.使用此控件的界面 xml 文件规则
布局规则如下图,lockView 即是我们正常显示内容的 View 它与表情输入控件 PandaEmoView 属于同一层级,父布局必须为纵向线性布局,且设置 lockView 权重为 1 ,PandaEmoView 高度包裹内容即可
4.使用控件的 Activity Java 代码设置
//界面控件初始化后 .attachEditText()绑定输入控件//初始化 KeyBoardManager,PandaEmoView.attachEditText() 必须在后调用
主要使用类及公有方法概览
PandaEmoEditText
表情输入框继承自
EditText
只对onKeyIme()
进行复写用于监听输入键盘或者软键盘的弹出与关闭
PandaEmoView
表情输入控件 View 继承自
RelativeLayout
PandaEmoManager
PandaEmoManager
为核心配置类,表情控件的各种参数都通过此类的构造器进行配置
剩余方法都为属性值的 getter() setter() 不在赘述。
PandaEmoManager.Builder
PandaEmoManager
的构造器类,属性及方法都与 PandaEmoManager 一一对应;
KeyBoardManager
KeyBoardManager
为输入法软键盘与表情输入控件协调管理类
EmoticonManager
EmoticonManager 为 emoji 表情加载管理类,此类提供方法将资源文件根据配置文件加载进内存,方法大多数为私有方法,源码中可查看注释。
StickerManager
StickerManager 为 sticker 表情加载管理类,此类提供方法将资源文件根据配置文件加载进内存,与 EmoticonManager 类似
PandaEmoTranslator
PandaEmoTranslator 为 emoji 表情 [文字] 转表情的转换工具类
关于内存优化
因为表情,gif 表情,自定义贴图,表情包贴图这些都涉及到图片资源加载到内存中。因此开发过程中不可避免的也遇到了许多的内存优化相关的问题。
工具
就地取材,直接使用 Android Studio 的 Monitors 工具可以直观的查看到应用运行过程中内存的变化过程
优化点1 —— Gif 播放类的优化
问题:
参考网上的 gif 图文混排项目,虽然实现了 gif 与文字的图文混排效果,但存在致命的缺陷。该项目中每一个 gif 动态表情图都有一个对应的 Runable 对象去执行 gif 图片的逐帧播放,当一个表情重复输入也会有新的 Runable 对象去执行这样的操作,这样做的后果就是当输入的表情数量增加时,所消耗的内存是持续增长的。这显然不能满足生产使用的需求。
解决方案:
考虑到此处内存增加的原因是让表情动起来的 Runable 泛滥引起的,因此减少 Runable 的数量就是解决此处内存问题的关键。我的方案做的比较彻底,整个应用 gif 表情这一块儿都交给一个 Runable 去处理,这个 Runable 在 PandaTranslator 中进行图文转化时会被初始化
// PandaTranslator 的 103 - 107 行 103 if (mGifRunnable == null) { 104 mGifRunnable = new GifRunnable(gifDrawable, mHandler); 105 } else { 106 mGifRunnable.addGifDrawable(gifDrawable); 107 }
因为 PandaTranslator 是一个单例实现,所以在他初始化后 mGifRunnable 也将保持唯一性。无论是新建初始化还是 addGifDrawable() 都是把 Gif 表情对象放入 GifRunnable 中的一个 Map 中。Map 的 key value 分别是表情控件依附的 Activity 的 LocalName 和 一个 AnimatedGifDrawable 的 List。在 GifRunnable 的 run 方法中会根据当前的 Activity 的 LocalName 去取出对应的 AnimatedGifDrawable 列表,遍历执行并按第一张 gif 表情的帧间隔去刷新 Drawable 并触发 TextView 刷新回调
@Override public void run() { isRunning = true; if (currentActivity != null) { List<AnimatedGifDrawable> runningDrawables = mGifDrawableMap.get(currentActivity); if (runningDrawables != null) { for (AnimatedGifDrawable gifDrawable : runningDrawables) { AnimatedGifDrawable.RunGifCallBack listener = gifDrawable.getUpdateListener(); List<AnimatedGifDrawable.RunGifCallBack> runningListener = listenersMap.get(currentActivity); if (runningListener != null) { // 避免一个 TextView 多个表情时重复添加回调 if (!runningListener.contains(listener)) { runningListener.add(listener); } } else { // 为空时肯定不存在直接添加 runningListener = new ArrayList<>(); runningListener.add(listener); listenersMap.put(currentActivity, runningListener); } gifDrawable.nextFrame(); } for (AnimatedGifDrawable.RunGifCallBack callBack : listenersMap.get(currentActivity)) { if (callBack != null) { callBack.run(); } } frameDuration = runningDrawables.get(0).getFrameDuration(); } } mHandler.postDelayed(this, frameDuration); }
这样就实现了全局使用一个 Runable 来执行 gif 动起来的任务,不同的界面也仅需要将该界面的 AnimatedGifDrawable 对象加入任务 Map 即可。
优化点2 —— 界面暂停或退出时 Gif 播放资源同步退出回收
上面说到的将 AnimatedGifDrawable 列表加入任务 Map,只进不出显然是不科学的也会持续增加内存的消耗。我们希望在 Activity 退出时能将将当前 Activity 的 AnimatedGifDrawable 列表销毁移除,在界面不可见但是可能会恢复时(pause 状态)暂停 Runable 的执行,减少资源消耗。于是 GifRunable 提供了如下三个方法给外部调用
/** * 使用了表情转换的界面退出时调用,停止动态图handler */ public void clearHandler(String activityName) { currentActivity = null; //清除当前页的数据 mGifDrawableMap.remove(activityName); // 当退出当前Activity后没表情显示时停止 Runable 清除所有动态表情数据 listenersMap.remove(activityName); if (mGifDrawableMap.size() == 0) { clearAll(); } } private void clearAll() { mHandler.removeCallbacks(this); mHandler.removeCallbacksAndMessages(null); mGifDrawableMap.clear(); isRunning = false; } /** * 启动运行 */ public void startHandler(String activityName) { currentActivity = activityName; if (mGifDrawableMap != null && mGifDrawableMap.size() > 0 && !isRunning) { run(); } }
它的调用入口都在 PandaTranslator 中,然后我们只需在使用到 PandaEmoView 或者直接在 BaseActivity 的 onResume(),onPause(),onDestory() 中分别调用以下三个方法:
PandaTranslator.getInstance().resumeGif(activityLocalName);PandaTranslator.getInstance().pauseGif();PandaTranslator.getInstance().clearGif(activityLocalName)
优化点3 —— 使用 LruCache 缓存 emoji 资源
根据 LRU 规则将表情 Gif 缓存,避免重复加载创建新对象。
最后
因为离职从南京回到成都还有工作的各种各样的原因,也是有四个多月没更博客了。这是重新开始写博客的第一篇,之后大概会以一个月 2-3 篇的样子更新,记录与分享,欢迎大家关注我的简书。
本库地址 https://github.com/PandaQAQ/PandaEmoView
欢迎 star 和提 issue
开源库
推荐几个开源库
仿微信表情输入键盘(支持 Gif 表情图文混排 )相关推荐
- 强大的图文长微博工具 支持图文混排 支持美工字体
功能:一键将写好的博客文章,同时发布到博客和微博,在微博上,自动生成图文长微博,一键发布.免费下载地址:http://www.juziseo.com/ .效果如下,支持长微博图文混排和美工字体,以及字 ...
- 为了用Unity来实现APP效果的页面,自制一个简易的图文混排系统。
图文混排设计方案 实现一个Unity支持的简单图文混排模块,实现时需要考虑尺寸适配的限制,设计思路是自定义标签,采用微信朋友圈里的那种流式布局,一行一个标签,做一个一维的列表,方便手动编辑也方便程序实 ...
- LaTeX的一般图文混排介绍
在日常的文档编辑工作中,图文混排还是比较常见的,本文介绍使用wrapfig与picinpar宏包来实现这一排版方式. 1.示例代码的验证环境 操作系统:Ubuntu 22.04 引擎:XeTeX 3. ...
- mysql emoy表情_GitHub - PandaQAQ/PandaEmoView: emoji gif 表情图文混排,仿微信表情输入...
该库具有以下特点: 支持 emoji 表情图片 支持 gif 动态表情输入显示 支持单张贴图表情(与微信收藏表情一致) 支持题图表情库的添加删除 效果图: 快速使用 引入库 compile 'com. ...
- 【游戏开发实战】Unity UGUI Text图文混排(聊天文字混表情),支持动态表情,出招吧表情帝
文章目录 一.前言 二.最终效果 三.具体使用 1.导入表情素材 2.设置图片格式 3.生成表情图集 4.UI-EmojiFont.shader 5.材质球 四.测试 五.结束语 一.前言 点关注不迷 ...
- 类似微信表情图文混排(本地自定义表情)
注:仅仅是提供思路 有些问题如隐藏系统自带的selectall按钮 自定义copy按钮 需要再解决 //首先引用 https://github.com/zekunyan/UITextViewDIYEm ...
- Unity Emoji表情(图文混排)2022最详细教程
文章目录 前言 一.emoji是什么? emoji (日本在无线通信中所使用的视觉情感符号) 二.使用步骤 1.将源码文件导入自己的项目中 步骤一:将Editor目录文件EmojiAtlasBaker ...
- ios 表情符号 键盘_iOS 表情键盘+gif聊天图文混排,看我的就够了
更新: 1.解决首次加载键盘卡顿的问题: 2.修改聊天布局方式,现在无需计算,更加丝滑. 前言: 之前做过[OC版本]和[swift版本]图文混排和表情键盘,说实在的很low,特别是键盘,整体只是实现 ...
- Swift3.0 功能二 (表情键盘与图文混排)
随着iOS越来越多表情键盘以及图文混排的需求,本文运用Swift3.0系统的实现其功能以及封装调用方法,写的不好,如有错误望各位提出宝贵意见,多谢 项目源码地址: 相关知识点都有标识 项目源码地址 废 ...
最新文章
- OKR和绩效管理如何一起工作?
- 线性回归与多项式回归的区别,如何判断他们的使用场景
- 编码练习——Java-8-输入/输出
- python读取word中后缀名docx的文件的表格
- linux 远程挂载摄像头_如何实现嵌入式Linux下USB摄像头视频采集
- Chrome JS断点调试技巧
- 编程之美4:求数组中的最大值和最小值
- ECMAScript 6细说转码的常见的几种方案
- R语言各个包里面的数据集
- Java保存书店每日交易记录
- 十级解读比特大陆内部信:比特大陆正在走向「詹克团化」
- Typora完整教程
- JS判断当前手机类型
- webGl shader的学习记录(六):如何画出一个渐变色填充的三角形
- 学习Vue3 第二十七章(自定义指令directive)
- linux rpm -qip命令,linux rpm命令
- Notion Like 笔记软件使用教程·学习资源汇总·知识管理方案
- 计算机英语测试,计算机专业英语测试
- 常见微商升级、返利制度设计详解
- 微信公众号申请到开发环境搭建