Android輸入框添加emoje表情表徵圖的實現代碼_Android

來源:互聯網
上載者:User

前言

再次寫聊天的時候才發現,代碼積累是一件非常重要的事情,就如這篇部落格的意圖其實就是代碼積累的目的,其實沒什麼難度,但是一件很瑣碎的事情真的也需要時間去完成和調試,所以,擷取你在寫一個功能的時候會覺得並沒有多難,但是如果可以最好把代碼整理/積累下來。

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:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:animateLayoutChanges="true"  android:orientation="vertical">  <include layout="@layout/chat_bottom_input"></include>  <include layout="@layout/chat_bottom_function1"></include></LinearLayout>

以下分別是 輸入框的 xml 和 Emoji 的 xml:

chat_bottom_input:

<?xml version="1.0" encoding="utf-8"?><merge xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical">  <RelativeLayout    android:id="@+id/rl_input"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="#f0f0f0">    <ImageView      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" />    <LinearLayout      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">      <ImageView        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" />      <EditText        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" />    </LinearLayout>  </RelativeLayout></merge>

chat_bottom_function1:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:background="#ffffff"  android:orientation="vertical">  <android.support.v4.view.ViewPager    android:id="@+id/emojes"    android:layout_width="match_parent"    android:layout_height="110dp"></android.support.v4.view.ViewPager></LinearLayout>

首先是 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<GridView> mLists;  public EmojiPageAdapter(Context context, ArrayList<GridView> 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<GridView> 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<Pattern, Integer> 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<Pattern, Integer> 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,能讀代碼,有沒有講解其實都還好,也不用怕自己之後看不懂了。

源碼下載:https://github.com/cjhandroid/EmojiInputDemo

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.