前言

再次写聊天的时候才发现,代码积累是一件非常重要的事情,就如这篇博客的意图其实就是代码积累的目的,其实没什么难度,但是一件很琐碎的事情真的也需要时间去完成和调试,所以,获取你在写一个功能的时候会觉得并没有多难,但是如果可以最好把代码整理/积累下来。

demo描述

demo的功能其实就是仿照微信的 聊天 emoje 选择,采用了 viewpager+gridView 的方案,不过有空我会补上 recyclerView 的方案,目前还是先把功能实现了再说。另外在 TextView 和 EditText 中添加 emoje ,可以看看这篇博客:Android中使用TextView及EditText来实现表情图标的显示及插入功能 ,这篇博客中介绍了两种方法:

方法一:使用Html.fromHtml解析,方法二:使用Bitmap直接画出来,我采用了第二种方法,使用bitmap画出来。

Read the fucking code

思路:既然是 viewpager + gridview 那么,先从大方向入手,完成 viewpager,再去完成 gridview。PS:代码里面使用了 RxJava、lambda、ButterKnife、EventBus、Glide。

这里将整个底部布局写成了一个组合的ViewGroup – ChatBottomBar,先从布局开始。

ChatBottomBar 的 XML – chat_bottom.xml:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:animateLayoutChanges="true"

android:orientation="vertical">

以下分别是 输入框的 xml 和 Emoji 的 xml:

chat_bottom_input:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/rl_input"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#f0f0f0">

android:id="@+id/showMore"

android:layout_width="42dp"

android:layout_height="60dp"

android:paddingBottom="5dp"

android:paddingLeft="9dp"

android:paddingTop="9dp"

android:src="@mipmap/ic_launcher" />

android:layout_width="match_parent"

android:layout_height="35dp"

android:layout_centerVertical="true"

android:layout_marginRight="15dp"

android:layout_toRightOf="@+id/showMore"

android:background="@drawable/shape_white_corner"

android:gravity="center_vertical"

android:orientation="horizontal">

android:layout_width="45dp"

android:layout_height="40dp"

android:paddingBottom="10dp"

android:paddingLeft="10dp"

android:paddingRight="5dp"

android:paddingTop="10dp"

android:src="@mipmap/ic_launcher" />

android:id="@+id/editText"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginRight="10dp"

android:background="@null"

android:gravity="center_vertical"

android:hint="说点什么"

android:maxLines="3"

android:textColor="#999999"

android:textColorHint="#dddddd"

android:textSize="13sp" />

chat_bottom_function1:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#ffffff"

android:orientation="vertical">

android:id="@+id/emojes"

android:layout_width="match_parent"

android:layout_height="110dp">

首先是 viewpager 填充 gridView,从 PageAdapter 看起,看看需要哪些数据:

package cjh.emojicondemo;

import android.content.Context;

import android.support.v4.view.PagerAdapter;

import android.support.v4.view.ViewPager;

import android.view.View;

import android.widget.GridView;

import java.util.ArrayList;

/**

* Created by cjh on 16-11-8.

*/

public class EmojiPageAdapter extends PagerAdapter {

private ArrayList mLists;

public EmojiPageAdapter(Context context, ArrayList array) {

this.mLists = array;

}

@Override

public int getCount() {

return mLists.size();

}

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

return arg0 == arg1;

}

@Override

public Object instantiateItem(View arg0, int arg1) {

((ViewPager) arg0).addView(mLists.get(arg1));

return mLists.get(arg1);

}

@Override

public void destroyItem(View arg0, int arg1, Object arg2) {

((ViewPager) arg0).removeView((View) arg2);

}

}

其实基本就是PagerAdapter的模板代码,需要的仅仅只是 gridView,看下在ChatbottomBar中的代码:

@BindView(R.id.emojes)

android.support.v4.view.ViewPager emojes;

....

//每一页有24个表情,然后使用Math的ceil函数,计算出我们需要的最小页数

private void initEmoje() {

int pageCount = (int) Math.ceil(EmojiUtils.emojis.length / 24.0f);

ArrayList pageData = new ArrayList<>();

for (int i = 0; i < pageCount; i++) {

GridView gv = getGridView(i);

pageData.add(gv);

}

emojes.setAdapter(new EmojiPageAdapter(context, pageData));

}

大结构基本就是这样了,接着就是小细节了,比如gridView的创建和展示:

@NonNull

private GridView getGridView(int i) {

GridView gv = new GridView(context);

gv.setVerticalScrollBarEnabled(false);

gv.setAdapter(new EmojiGridAdapter(context, i));

gv.setGravity(Gravity.CENTER);

gv.setClickable(true);

gv.setFocusable(true);

gv.setNumColumns(8);

return gv;

}

adapter:

package cjh.emojicondemo;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import org.greenrobot.eventbus.EventBus;

/**

* Created by cjh on 16-11-8.

*/

public class EmojiGridAdapter extends BaseAdapter {

private Context context;

private int page;

public EmojiGridAdapter(Context context, int page) {

this.context = context;

this.page = page;

}

@Override

public int getCount() {

return 24;

}

@Override

public Object getItem(int i) {

return null;

}

@Override

public long getItemId(int i) {

return 0;

}

@Override

public View getView(int i, View view, ViewGroup viewGroup) {

ViewHolder holder = null;

if (view == null) {

view = LayoutInflater.from(context).inflate(R.layout.chat_emoji, null);

holder = new ViewHolder();

holder.image = (ImageView) view.findViewById(R.id.image);

view.setTag(holder);

}

holder = (ViewHolder) view.getTag();

int position = page * 23 + i;

if (position < EmojiUtils.emojis.length)

ImageLoader.load(context, EmojiUtils.icons[position], holder.image);

else

holder.image.setVisibility(View.GONE);

holder.image.setOnClickListener(view1 -> EventBus.getDefault().post(new EmojiEvent(EmojiUtils.emojis[page * 23 + i])));

return view;

}

static class ViewHolder {

public ImageView image;

}

}

在这里,点击时间的传递我使用的是EventBus。

大结构基本已经OK了,接着就要看比较核心的部分,Emoji 的处理,在接收到Event事件时,调用了chatBottomBar.appandEmoje(emojiEvent.s)

@Subscribe

public void onEmojiEvent(EmojiEvent emojiEvent) {

chatBottomBar.appandEmoje(emojiEvent.s);

}

那么来看看ChatBottomBar的代码:

public void appandEmoje(String s) {

rx.Observable

.just(s)

.subscribeOn(Schedulers.io())

.map(s1 -> {

SpannableString emojeText = EmojiUtils.getEmojiText(editText.getText().toString() + s1);

return emojeText;

})

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(s2 -> {

editText.setText("");

editText.append(s2);

});

}

上面代码使用了RXJAVA,可以看到真正的核心是在

EmojiUtils.getEmojiText(editText.getText().toString() + s1);

return emojeText;这行代码里面。

那么就来看看 EmojiUtils 的代码吧:

package cjh.emojicondemo;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.drawable.Drawable;

import android.net.Uri;

import android.text.Spannable;

import android.text.SpannableString;

import android.text.TextUtils;

import android.text.style.ImageSpan;

import android.text.style.RelativeSizeSpan;

import android.util.SparseArray;

import java.io.File;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import java.util.zip.Inflater;

/**

* Created by cjh on 16-11-7.

*/

public class EmojiUtils {

private static HashMap emoMap = new HashMap<>();

public static final String DELETE_KEY = "em_delete_delete_expression";

public static String[] emojis = new String[]{

"[微笑]",

"[撇嘴]",

"[色]",

"[发呆]",

"[得意]",

"[流泪]",

"[害羞]",

"[闭嘴]",

"[睡]",

"[大哭]",

"[尴尬]",

"[发怒]",

"[调皮]",

"[呲牙]",

"[惊讶]",

"[难过]",

"[酷]",

"[冷汗]",

"[抓狂]",

"[吐]",

"[偷笑]",

"[愉快]",

"[白眼]",

"[傲慢]",

"[饥饿]",

"[困]",

"[惊恐]",

"[流汗]",

"[憨笑]",

"[悠闲]",

"[奋斗]",

"[咒骂]",

"[疑问]",

"[嘘]",

"[晕]",

"[疯了]",

"[衰]",

"[骷髅]",

"[敲打]",

"[再见]",

"[擦汗]",

"[抠鼻]",

"[鼓掌]",

"[糗大了]",

"[坏笑]",

"[左哼哼]",

"[右哼哼]",

"[哈欠]",

"[鄙视]",

"[委屈]",

"[快哭了]",

"[阴险]",

"[亲亲]",

"[吓]",

"[可怜]",

"[菜刀]",

"[西瓜]",

"[啤酒]",

"[篮球]",

"[乒乓]",

"[咖啡]",

"[饭]",

"[猪头]",

"[玫瑰]",

"[凋谢]",

"[嘴唇]",

"[爱心]",

"[心碎]",

"[蛋糕]",

"[闪电]",

"[炸弹]",

"[刀]",

"[足球]",

"[瓢虫]",

"[便便]",

"[月亮]",

"[太阳]",

"[礼物]",

"[拥抱]",

"[强]",

"[弱]",

"[握手]",

"[胜利]",

"[抱拳]",

"[勾引]",

"[拳头]",

"[差劲]",

"[爱你]",

"[NO]",

"[OK]"

};

public static int[] icons = new int[]{

R.drawable.ee_1,

R.drawable.ee_2,

R.drawable.ee_3,

R.drawable.ee_4,

R.drawable.ee_5,

R.drawable.ee_6,

R.drawable.ee_7,

R.drawable.ee_8,

R.drawable.ee_9,

R.drawable.ee_10,

R.drawable.ee_11,

R.drawable.ee_12,

R.drawable.ee_13,

R.drawable.ee_14,

R.drawable.ee_15,

R.drawable.ee_16,

R.drawable.ee_17,

R.drawable.ee_18,

R.drawable.ee_19,

R.drawable.ee_20,

R.drawable.ee_21,

R.drawable.ee_22,

R.drawable.ee_23,

R.drawable.ee_24,

R.drawable.ee_25,

R.drawable.ee_26,

R.drawable.ee_27,

R.drawable.ee_28,

R.drawable.ee_29,

R.drawable.ee_30,

R.drawable.ee_31,

R.drawable.ee_32,

R.drawable.ee_33,

R.drawable.ee_34,

R.drawable.ee_35,

R.drawable.ee_36,

R.drawable.ee_37,

R.drawable.ee_38,

R.drawable.ee_39,

R.drawable.ee_40,

R.drawable.ee_41,

R.drawable.ee_42,

R.drawable.ee_43,

R.drawable.ee_44,

R.drawable.ee_45,

R.drawable.ee_46,

R.drawable.ee_47,

R.drawable.ee_48,

R.drawable.ee_49,

R.drawable.ee_50,

R.drawable.ee_51,

R.drawable.ee_52,

R.drawable.ee_53,

R.drawable.ee_54,

R.drawable.ee_55,

R.drawable.ee_56,

R.drawable.ee_57,

R.drawable.ee_58,

R.drawable.ee_59,

R.drawable.ee_60,

R.drawable.ee_61,

R.drawable.ee_62,

R.drawable.ee_63,

R.drawable.ee_64,

R.drawable.ee_65,

R.drawable.ee_66,

R.drawable.ee_67,

R.drawable.ee_68,

R.drawable.ee_69,

R.drawable.ee_70,

R.drawable.ee_71,

R.drawable.ee_72,

R.drawable.ee_73,

R.drawable.ee_74,

R.drawable.ee_75,

R.drawable.ee_76,

R.drawable.ee_77,

R.drawable.ee_78,

R.drawable.ee_79,

R.drawable.ee_80,

R.drawable.ee_81,

R.drawable.ee_82,

R.drawable.ee_83,

R.drawable.ee_84,

R.drawable.ee_85,

R.drawable.ee_86,

R.drawable.ee_87,

R.drawable.ee_88,

R.drawable.ee_89,

R.drawable.ee_90,

};

static {

for (int i = 0; i < emojis.length; i++) {

emoMap.put(Pattern.compile(Pattern.quote(emojis[i])), icons[i]);

}

}

public static SpannableString getEmojiText(String s) {

SpannableString spannable = new SpannableString(s);

for (Map.Entry entry : emoMap.entrySet()) {

Matcher matcher = entry.getKey().matcher(spannable);

while (matcher.find()) {

for (ImageSpan span : spannable.getSpans(matcher.start(),

matcher.end(), ImageSpan.class))

if (spannable.getSpanStart(span) >= matcher.start()

&& spannable.getSpanEnd(span) <= matcher.end())

spannable.removeSpan(span);

else

break;

Drawable drawable = MainActivity.context.getResources().getDrawable(entry.getValue());

drawable.setBounds(0, 0, 60, 60);

ImageSpan imageSpan = new ImageSpan(drawable);

spannable.setSpan(imageSpan,

matcher.start(), matcher.end(),

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

return spannable;

}

}

这里为了方便知道插入表情的位置,我将emoji对应的中文转化成了Pattern对象,在getEmojiText里面做了遍历查询比对,这也就是为什么我会使用RX来异步操作。

基本就到这里了,回过来看写的内容,自己都懒得吐槽,不过,好在只要有具体的demo,能读代码,有没有讲解其实都还好,也不用怕自己之后看不懂了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android添加文本框代码,Android输入框添加emoje表情图标的实现代码相关推荐

  1. Java 添加音频到ppt_Java 添加文本框到PPT幻灯片过程解析

    本文将介绍图和通过Java程序添加文本框到PPT幻灯片的方法.包括设置文本框边框样式.填充效果.阴影效果.文本框旋转.文字样式等. 使用工具:Free Spire.Presentation for J ...

  2. (转)完美解决 Android WebView 文本框获取焦点后自动放大有关问题

    完美解决 Android WebView 文本框获取焦点后自动放大问题 前几天在写一个项目时,要求在项目中嵌入一个WebView 本来很快就完成了,测试也没有问题.但发给新加坡时,他们测试都会出现文本 ...

  3. 完美解决 Android WebView 文本框获取焦点后自动放大问题

    前几天在写一个项目时,要求在项目中嵌入一个WebView 本来很快就完成了,测试也没有问题.但发给新加坡时,他们测试都会出现文本框聚焦时,网页面会放大(他们用三星手机测试的) 网上查了好久参考他的方法 ...

  4. java中添加文本框_Java 添加、删除Word文档中的文本框

    在Word文档中,文本框是指一种可移动.可调大小的文字或图形容器.使用文本框,能够使文档在内容和形式上更为饱满.本文将通过使用Java编程来演示如何添加.删除Word文档中的文本框. Jar文件获取及 ...

  5. R语言ggplot2在可视化图像中添加横线并在横线中添加文本、为横线中添加的文本添加文本框、自定义文本框的填充色(background color for a text annotation)

    R语言ggplot2在可视化图像中添加横线并在横线中添加文本.为横线中添加的文本添加文本框.自定义文本框的填充色(background color for a text annotation) 目录

  6. R语言ggplot2包和ggtext包在可视化图像中的指定位置添加文本框(横向文本框、竖向文本框)

    R语言ggplot2包和ggtext包在可视化图像中的指定位置添加文本框(横向文本框.竖向文本框) 目录

  7. layui弹出层中添加文本框

    有时候,我们需要针对,审核时给出原因这一需求,在弹出层添加文本框,比如 这时候就用到了 layer.prompt() var remarkReason = "";layer.pro ...

  8. Python Excel操作模块XlsxWriter之添加文本框 worksheet.insert_textbox()

    worksheet.insert_textbox() insert_textbox(row, col, textbox[, options]) 向工作表单元格添加文本框. 参数: row(int) - ...

  9. 列表文本框html,HTML列表添加文本框

    我需要你的帮助我想每次向列表中添加一种成分时都要放一个小文本框.就在它旁边,我可以把数量.有人能帮助我吗? 下面是HTML:HTML列表添加文本框 Ingredient Nombre Receta: ...

最新文章

  1. django文件上传
  2. mysql8 my 010457_分享一下我在mysql5.6+mysql8数据库安装过程中的一些坑!
  3. 计算机学院杨洋,美国莱特州立大学吴志强教授访问计算机科学与技术学院
  4. 自行编译Vim for Windows,加入Python支持!
  5. 从编译原理看一个解释器的实现
  6. Netty入门官方例子
  7. HAProxy 的负载均衡服务器,Redis 的缓存服务器
  8. Gym - 101981I-MagicPotion-最大流
  9. C# webbrowser 代理
  10. 在vue项目中操作元素ref案例;
  11. Altium Designer如何画虚线
  12. 不好意思,00后黑客CEO登场了!
  13. Go底层剖析 | 好书中秋赠送中
  14. Cacti实现网络监控的使用心得(1)
  15. html中可以编辑的文本,用BeautifulSoup编辑html中的文本
  16. 技巧心得:DOS学习心得(一)
  17. keil4在线仿真教程分享
  18. 普渡大学计算机科学本科,美国普渡大学计算机科学CS本科申请条件及案例
  19. TiDB-explain详解
  20. pandas数据处理:常用却不甚了解的函数,pd.read_excel()

热门文章

  1. 问题:惠普笔记本 ZHAN 66 如何进入BIOS,解决虚拟机打不开的问题?
  2. maven打包指定jdk的版本
  3. 来自一个从业多年程序员的春招,三面字节+四面字节+拼多多终面!
  4. php SESSION和COOKIE实用详解
  5. Mpp 的一种 java 读写解决方案
  6. 【MBTI】INFJ人格报告书
  7. “十四五”开局丨数字经济的技术底座呈现哪些新特征?
  8. python自学篇十[ 面向对象 (四) :王者荣耀小游戏+模拟一个简单的银行进行业务办理的类]
  9. ATA-2161高压放大器在微流控技术细胞分选中的应用
  10. linux基础-常用工具-rarlinux