作者 | 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 自定义

  1. 应用 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 表情图文混排 )相关推荐

  1. 强大的图文长微博工具 支持图文混排 支持美工字体

    功能:一键将写好的博客文章,同时发布到博客和微博,在微博上,自动生成图文长微博,一键发布.免费下载地址:http://www.juziseo.com/ .效果如下,支持长微博图文混排和美工字体,以及字 ...

  2. 为了用Unity来实现APP效果的页面,自制一个简易的图文混排系统。

    图文混排设计方案 实现一个Unity支持的简单图文混排模块,实现时需要考虑尺寸适配的限制,设计思路是自定义标签,采用微信朋友圈里的那种流式布局,一行一个标签,做一个一维的列表,方便手动编辑也方便程序实 ...

  3. LaTeX的一般图文混排介绍

    在日常的文档编辑工作中,图文混排还是比较常见的,本文介绍使用wrapfig与picinpar宏包来实现这一排版方式. 1.示例代码的验证环境 操作系统:Ubuntu 22.04 引擎:XeTeX 3. ...

  4. mysql emoy表情_GitHub - PandaQAQ/PandaEmoView: emoji gif 表情图文混排,仿微信表情输入...

    该库具有以下特点: 支持 emoji 表情图片 支持 gif 动态表情输入显示 支持单张贴图表情(与微信收藏表情一致) 支持题图表情库的添加删除 效果图: 快速使用 引入库 compile 'com. ...

  5. 【游戏开发实战】Unity UGUI Text图文混排(聊天文字混表情),支持动态表情,出招吧表情帝

    文章目录 一.前言 二.最终效果 三.具体使用 1.导入表情素材 2.设置图片格式 3.生成表情图集 4.UI-EmojiFont.shader 5.材质球 四.测试 五.结束语 一.前言 点关注不迷 ...

  6. 类似微信表情图文混排(本地自定义表情)

    注:仅仅是提供思路 有些问题如隐藏系统自带的selectall按钮 自定义copy按钮 需要再解决 //首先引用 https://github.com/zekunyan/UITextViewDIYEm ...

  7. Unity Emoji表情(图文混排)2022最详细教程

    文章目录 前言 一.emoji是什么? emoji (日本在无线通信中所使用的视觉情感符号) 二.使用步骤 1.将源码文件导入自己的项目中 步骤一:将Editor目录文件EmojiAtlasBaker ...

  8. ios 表情符号 键盘_iOS 表情键盘+gif聊天图文混排,看我的就够了

    更新: 1.解决首次加载键盘卡顿的问题: 2.修改聊天布局方式,现在无需计算,更加丝滑. 前言: 之前做过[OC版本]和[swift版本]图文混排和表情键盘,说实在的很low,特别是键盘,整体只是实现 ...

  9. Swift3.0 功能二 (表情键盘与图文混排)

    随着iOS越来越多表情键盘以及图文混排的需求,本文运用Swift3.0系统的实现其功能以及封装调用方法,写的不好,如有错误望各位提出宝贵意见,多谢 项目源码地址: 相关知识点都有标识 项目源码地址 废 ...

最新文章

  1. OKR和绩效管理如何一起工作?
  2. 线性回归与多项式回归的区别,如何判断他们的使用场景
  3. 编码练习——Java-8-输入/输出
  4. python读取word中后缀名docx的文件的表格
  5. linux 远程挂载摄像头_如何实现嵌入式Linux下USB摄像头视频采集
  6. Chrome JS断点调试技巧
  7. 编程之美4:求数组中的最大值和最小值
  8. ECMAScript 6细说转码的常见的几种方案
  9. R语言各个包里面的数据集
  10. Java保存书店每日交易记录
  11. 十级解读比特大陆内部信:比特大陆正在走向「詹克团化」
  12. Typora完整教程
  13. JS判断当前手机类型
  14. webGl shader的学习记录(六):如何画出一个渐变色填充的三角形
  15. 学习Vue3 第二十七章(自定义指令directive)
  16. linux rpm -qip命令,linux rpm命令
  17. Notion Like 笔记软件使用教程·学习资源汇总·知识管理方案
  18. 计算机英语测试,计算机专业英语测试
  19. 常见微商升级、返利制度设计详解
  20. 微信公众号申请到开发环境搭建

热门文章

  1. 2020年webpack面试题
  2. python PIL获取图片像素点
  3. Matlab——行星轨道问题
  4. CISCO PACKET TRACER 实验:以太网连接Internet
  5. MSTAR数据库结合深度学习(SAR图像目标检测与识别)
  6. 蓄水池算法的设计和实现
  7. 资料搜集-JAVA系统的梳理知识3-面试篇
  8. 怎么做AE文字翻页动效?3步学会制作文字翻页
  9. python 福利吧_段友福利:Python爬取段友之家贴吧图片和小视频
  10. kdj值应用口诀_KDJ指标应用口诀