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

前言

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

demo描述

7fa191c56f383f6478f419cb9c28b455.gif

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,能读代码,有没有讲解其实都还好,也不用怕自己之后看不懂了。

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值