1. 程式人生 > >Android使用SpannableString實現文字框裡插入表情

Android使用SpannableString實現文字框裡插入表情

效果

         

介紹

       SpannableString,相較於普通String帶有豐富的格式設定,可使文字的可讀性更強。兩者都用於儲存字串,而SpannableString的特殊之處就在於有一個setSpan()函式,因而能給儲存的文字新增各種樣式,諸如文字顏色樣式((ForgroundColorSpan),文字背景顏色樣式((BackgroundColorSpan)下劃線樣式((UnderlineSpan)等,而今天我們的功能實現需要用到的則是圖片樣式(ImageSpan)。

       SpannableStringBuilder,類似於StringBuilder,可以通過其append()方法拼接多個String。而SpannableString則類似於String,構造物件對傳入一個String,之後再也無法更改String的內容,也無法拼接多個SpannableString。

       相關API的類大致分層如下:

        由上圖可看出,由於Spannable等最終都實現了CharSequence介面,所以可以直接將SpannableString和SpannableStringBuillder通過TextView.setText()方法設定給TextView。

實現

主要就是實現自定義控制元件類,然後覆寫setText()方法

package com.example.emodemo.view;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.widget.TextView;

public class EmoticonsTextView extends TextView {

    public EmoticonsTextView(Context context) {
        super(context);
    }

    public EmoticonsTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public EmoticonsTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        if (!TextUtils.isEmpty(text)) {
            super.setText(replace(text.toString()), type);
        } else {
            super.setText(text, type);
        }
    }

    private Pattern buildPattern() {
        return Pattern.compile("\\[f[0-9]{3}]", Pattern.CASE_INSENSITIVE);
    }

    private CharSequence replace(String text) {
        try {
            SpannableString spannableString = new SpannableString(text);
            int start = 0;
            Pattern pattern = buildPattern();
            Matcher matcher = pattern.matcher(text);
            while (matcher.find()) {
                String faceText = matcher.group();
                String key = faceText.substring(1);
                key = key.substring(key.indexOf("[")+1, key.indexOf("]"));
                BitmapFactory.Options options = new BitmapFactory.Options();
                Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),
                        getContext().getResources().getIdentifier(key, "drawable", getContext().getPackageName()), options);
                ImageSpan imageSpan = new ImageSpan(getContext(), bitmap);
                int startIndex = text.indexOf(faceText, start);
                int endIndex = startIndex + faceText.length();
                if (startIndex >= 0)
                    spannableString.setSpan(imageSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                start = (endIndex - 1);
            }
            return spannableString;
        } catch (Exception e) {
            return text;
        }
    }
}

這裡重點解析replace(String text)方法:

1.

SpannableString spannableString = new SpannableString(text);

構建SpannableString物件,傳入一個String(可以是純文字,可以是表情程式碼,也可以是文字和表情程式碼混合);

2.

Pattern pattern = buildPattern();
private Pattern buildPattern() {
        return Pattern.compile("\\[f[0-9]{3}]", Pattern.CASE_INSENSITIVE);
    }

將給定的正則表示式編譯並賦予給Pattern類。這裡你可以理解為制定了表情程式碼的正則表示式,文字中符合這個正則表示式的都是表情程式碼,即制定了一個篩選規則,用於篩選出文字中的表情程式碼。

這裡的正則表示式含義為[f(連續三位0-9的整數)],如[f001],[f002],[f003]等。

3.

Matcher matcher = pattern.matcher(text);

 生成一個給定命名的Matcher物件。你可以把這段程式碼理解為,是將上面制定的篩選規則輸入了一臺篩選機器,然後等待篩選。

4.

while (matcher.find()) {

嘗試在目標字串裡查詢下一個匹配子串。即進行遍歷篩選,如果找到匹配子串,則會返回true;

5.

String faceText = matcher.group()
返回當前查詢而獲得的與組匹配的子串內容。即取得篩選出的表情程式碼。

6.

key = key.substring(key.indexOf("[")+1, key.indexOf("]"));

取得"["和"]"內表情程式碼對應的資源命名,之後就通過該資源名在drawable資料夾中找到對應的圖片資源,解析為Bitmap物件:

BitmapFactory.Options options = new BitmapFactory.Options();
				Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),
						getContext().getResources().getIdentifier(key, "drawable", getContext().getPackageName()), options);

7.

ImageSpan imageSpan = new ImageSpan(getContext(), bitmap);
int startIndex = text.indexOf(faceText, start);
                int endIndex = startIndex + faceText.length();

傳入Bitmap引數,構建ImageSpan物件。然後取得該表情程式碼在完整字串中的起始索引和結束索引,即計算該表情的插入位置。

之後即可呼叫setSpan()方法將文字中的表情程式碼替換為表情圖片了。

8.

spannableString.setSpan(imageSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);   

這裡的第四個引數flag用於控制行為,取值包括如下:

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前後都不包括,即在指定範圍的前面和後面再插入新字元都不會應用該樣式 Spannable.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,後面包括。即僅在範圍字元的後面再插入新字元時才會應用該樣式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,後面不包括。
Spannable.SPAN_INCLUSIVE_INCLUSIVE:前後都包括。

原始碼

http://download.csdn.net/detail/alfred_c/9140067

參考

http://blog.csdn.net/harvic880925/article/details/38984705

http://www.bmob.cn

相關推薦

Android使用SpannableString實現文字插入表情

效果           介紹        SpannableString,相較於普通String帶有豐富的格式設定,可使文字的可讀性更強。兩者都用於儲存字串,而SpannableString的特殊之處就在於有一個setSpan()函式,因而能給儲存的文字新增各種樣式,諸

前端實現文字在游標後插入圖片

為解決這個問題,我們需要先整理一下步驟: 1、從剪貼簿中讀出圖片 2、將圖片轉為base64編碼 3、將圖片存入游標的位置 1、(1)我們可以通過設定div監聽paste事件 document.querySelector('#ed

react實現文字與state的雙向繫結

  <input type="text" value={this.state.msg} onChange={()=>this.txtChanged()} /> //第一種方法,用e。在onChange事件被觸發的時候,呼叫txtChanged方法,將得到的值

使用jquery實現文字輸入特效:文字逐個顯示逐個消失反覆迴圈

        前兩天看到某個網站上的輸入框有個小特效:文字逐個顯示,並且到字串最大長度後,逐個消失,然後重新迴圈顯示消失,迴圈顯示字串陣列。我對這個小特效有點好奇,於是今天自己嘗試用jquery寫一個簡單的小demo,終於把效果整出來了。首先看一下實現後的效果:

文字如何帶上圖示和文字提示

這裡是一個輸入框,裡面有提示文字的同時,還有一個小圖示。這裡我的做法是使用一個父元素包裹住文字框,利用父級元素的背景圖片來完成小圖示的實現。提示文字部分則使用文字框的placeholder來解決。 參考程式碼如下: HTML部分: <div class="

jquery實現文字的禁用和啟用

1,開啟disabled,設定input不可編輯  程式碼示例: $("#id").attr("disabled","disabled"); 2,關閉disabled 程式碼示例: $("#id").removeAttr("disabled"); 普通js中是這樣寫的

【C#】 如何實現文字歷史記錄提示功能

每次看到百度你輸入一個字元下面就會出現一大堆提示的近似的詞條,有沒有覺得很神奇呢?一起來看看是如何實現的吧! 正文 第一步:選擇窗體的Load事件 第二步新增如下程式碼 #region//提示歷史記錄功能 DataTable dt = lo

jQuery實現文字回車鍵提交form表單

<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>131</title><script src="http://ajax.aspne

jQuery實現文字回車鍵轉tab鍵

 <script type="text/javascript">         //功能:將回車鍵轉tab鍵         jQuery(function () {          

js實現文字賦值_value與innerHTML區別

例子,有如下input文字框: <input type="test" name="testName" id="testId"> 賦值操作: <script language="javascript">document.getElementById("

vue富文字插入文字、圖片、視訊)的使用

今天在vue裡面插入富文字遇到了一些小坑在這裡提供給大家用於參考,如有錯誤,望多加指正。 我這裡使用的是Element-ui的上傳圖片元件 首先引入Element-ui(這個我就不作贅述了,詳情參考element中文官網) 在引入富文字元件vue-quill-edito

js實現文字回車切換焦點

一段小指令碼 實現功能:文字框回車切換焦點 <script> function foo(){ var items=document.getElementsByName('key[]'); var item=null; for(var i=0;

Canvas實現文字

在canvas類裡呼叫textbox      private   TextBox   inputName   =   null;      private   Command   cCancel   =   new   Command("cancel",   Command

Jquery實現文字得到焦點的時候,文字的焦點出現在最後!

在前端開發中,有時我們為了客戶更好的體驗,需要使用js處理一些css解決不了的問題 比如,當文字框的文字多餘文字框的時候,有一部分文字沒有出來的時候,我們點選文字框,讓焦點出現在最後面,這樣子可以提高使用者的體驗 這裡舉個例子來說明一下 比如這種情況

分享一個只能在input文字輸入正負整數的正則表示式

<input type="text"  onkeyup="if(value.length==1){value=value.replace(/[^(\-?)\d+]/ig,'')}else{value=value.

js將字串作為函式名呼叫,實現input文字等form表單元素回車鍵統一事件響應

  通過給文字框<input enterKey=“fnName” />設定enterKey=“fnName”,頁面載入完後會自動繫結input的keydown事件,捕捉到回車鍵則呼叫fnName函式,如select等其它form元素也可以。要實現form表單元素回車鍵統一事件響應

layui文字實現選擇起始時間和結束時間

首先要呼叫layui時間外掛必須下載layui.js檔案,這個可以在官網去下載的(https://www.layui.com/),我這個功能是可以選擇當前時間的前一天,或者後一小時的時間,這個根據具體需求可以修改的: 如下圖所示: html程式碼:  <!DOCTY

js如何實現不能文字貼上

1.onpaste 2.在angular中有一指令 AngularJS ng-paste 指令   指令詳解 運用當前指令 在貼上時執行方法彈出對話方塊 清空文字框 <!DOCTYPE html>

webdriver獲取一個文字的value

今天在寫selenium自動化時,遇到一個問題 場景是這樣的,我要驗證一個使用者個人資訊修改功能是否生效,就修改了頁面的一個電話號碼的值, 這個元素是這樣的   <input type="text" class="field-text" name="phone"

android實現帶下拉列表的文字

android實現帶下拉列表的文字框 keywords:android studio、EditText、ImageView、PopupMenu。 佈局 <TextView android:layout_width="wrap_c