先提一下需求,用一個自定義EditText實現禁止輸入表情。談一下自定義控制項中自定義屬性的定義和使用方式。 第一步當然是自定義類EditTextNoEmoji繼承EditText,同時重寫三個構造方法。這裡需要註意的是,三個構造方法中必須分別實現父類對應的構造方法,就是三個super();而不能出現 ...
先提一下需求,用一個自定義EditText實現禁止輸入表情。談一下自定義控制項中自定義屬性的定義和使用方式。
第一步當然是自定義類EditTextNoEmoji繼承EditText,同時重寫三個構造方法。這裡需要註意的是,三個構造方法中必須分別實現父類對應的構造方法,就是三個super();而不能出現調用當前類的不同參數的另一個構造方法的形式,就是不能出現this()。否則的話,這個控制項在實際使用時是獲得不到焦點的,似乎是由於EditText繼承TextView的原因,具體原因待查。
談談這三個構造方法的區別,一參的構造EditTextNoEmoji(Context context),是在使用的java文件中動態生成時調用,兩參的構造EditTextNoEmoji(Context context, AttributeSet attrs),是在使用的xml文件中靜態生成時調用,三參的構造基本不會使用,暫且不討論。而兩參構造中的第二個參數attrs,正是我們要自定義的屬性,所以在該方法中調用setAttrs(context, attrs)設置xml文件中使用到的自定義屬性。
1 public EditTextNoEmoji(Context context) {
2 super(context);
3 }
4
5 public EditTextNoEmoji(Context context, AttributeSet attrs) {
6 super(context, attrs);
7 setAttrs(context, attrs);
8 }
9
10 public EditTextNoEmoji(Context context, AttributeSet attrs, int defStyle) {
11 super(context, attrs, defStyle);
12 setAttrs(context, attrs);
13 }
第二步需要聲明自定義屬性控制是否禁止輸入表情,同時為了方便該控制項在使用時的xml佈局中配置該屬性,要先在res/values/styles.xml中自定義屬性名稱。自定義屬性的styleable名稱必須是和自定義控制項的類名保持一致的,在這個樣式下可以添加任意的自定義屬性,如下代碼,添加了一個boolean類型的屬性,名稱為canInputEmoji。另外可以添加的屬性類型包括 color,boolean,dimension,enum,flag,float,fraction,integer,reference,string等十種。這裡定義的屬性如下所示。
1 <declare-styleable name="EditTextNoEmoji"> 2 <attr name="canInputEmoji" format="boolean"/> 3 </declare-styleable>
接下來要回到剛剛的EditTextNoEmoji類中繼續寫setAttrs(Context context, AttributeSet attrs)裡邊的內容了,接著看代碼。
1 //自定義屬性,控制是否輸入表情
2 private boolean canInputEmoji;
3
4 private void setAttrs(Context context, AttributeSet attrs){
5 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.EditTextNoEmoji);
6 canInputEmoji=typedArray.getBoolean(R.attr.canInputEmoji, false);
7 }
上文提到如果在java文件中動態使用該控制項,就是調用一參的構造,那上文的方式就不好使了,所以需要提供對該屬性的封裝,
1 public boolean canInputEmoji() {
2 return canInputEmoji;
3 }
4
5 public void setCanInputEmoji(boolean canInputEmoji) {
6 this.canInputEmoji = canInputEmoji;
7 }
最後重寫EditText的onTextChanged()方法即可,同時自定義屬性在該方法中判斷,代碼如下。
1 @Override
2 protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
3 super.onTextChanged(text, start, lengthBefore, lengthAfter);
4 if(canInputEmoji()){
5 int index = getSelectionStart() - 1;
6 if (index > 0) {
7 if (isEmojiChar(text.charAt(index))) {
8 Editable edit = getText();
9 edit.delete(text.length() - 2, text.length());
10 }
11 }
12 }
13 }
下麵貼上判斷字元是否為表情字元的方法。
1 /**
2 * 判斷字元是否是表情符號
3 * @param inputChar
4 * @return
5 */
6 private boolean isEmojiChar(char inputChar) {
7 return !((inputChar == 0x0) || (inputChar == 0x9) || (inputChar == 0xA) || (inputChar == 0xD) || ((inputChar >= 0x20) && inputChar <= 0xD7FF)) || ((inputChar >= 0xE000) && (inputChar <= 0xFFFD)) || ((inputChar >= 0x10000) && (inputChar <= 0x10FFFF));
8 }