最近項目中要求自己做一個發(fā)布話題和動態(tài)的功能,仿照微博的發(fā)布自己手?jǐn)]了一個自定義EditText舶治,支持話題標(biāo)簽添加分井,@某人標(biāo)簽,以及標(biāo)簽文字顏色的自定義霉猛,標(biāo)簽字符的自定義:直接上代碼:
首先 先寫atrrs文件:
<attr name="topic_tag" format="string">
<attr name="topic_text_color" format="color">
<attr name="topic_person_color" format="color">
<attr name="topic_person" format="string">
</declare-styleable>
然后直接上代碼:
package com.modian.framework.ui.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.modian.framework.R;
import java.util.ArrayList;
import java.util.List;
/**
* 發(fā)布話題自定義 EditText
*
*
* android:id="@+id/editText"
* android:layout_width="match_parent"
* android:layout_height="wrap_content"
* app:topic_text_color="#A128CE" 話題標(biāo)簽顏色
* app:topic_person_color="#E18A21" @某人 標(biāo)簽的顏色
* app:topic_tag="6" 話題標(biāo)簽字符
* app:topic_person="Y"/> @某人字符
*
*/
public class MDTopicEditTextViewextends androidx.appcompat.widget.AppCompatEditTextimplements TextWatcher, View.OnKeyListener {
public static final int TOPIC_TYPE_TOPIC =1;//話題標(biāo)簽
public static final int TOPIC_TYPE_PERSON =2;//話題標(biāo)簽@某人
private static final StringTOPIC_TAG ="#"; //默認(rèn)的話題標(biāo)簽前后標(biāo)識為 #
private static final int TOPIC_TEXT_COLOR = Color.parseColor("#FF0000"); //默認(rèn)的話題標(biāo)簽文本顏色
private static final int TOPIC_PERSON_COLOR = Color.parseColor("#FFCC00"); //默認(rèn)的話題標(biāo)簽文本顏色
private static final StringTOPIC_PERSON ="@"; //默認(rèn)的話題@用戶的標(biāo)識為@
private ListtopicList =new ArrayList<>(); //定義一個話題的list尺锚,存放插入的話題標(biāo)簽
private Stringtopic_tag =TOPIC_TAG;
private Stringtopic_person =TOPIC_PERSON;
private int topic_text_color =TOPIC_TEXT_COLOR;
private int topic_person_color =TOPIC_PERSON_COLOR;
private int index = -1;
private boolean isBack =false; //是否按了返回鍵
public MDTopicEditTextView(@NonNull Context context) {
this(context,null);
}
public MDTopicEditTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context,attrs, R.attr.editTextStyle);
}
public MDTopicEditTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MDTopicEditTextView);
topic_tag = typedArray.getString(R.styleable.MDTopicEditTextView_topic_tag);
if(TextUtils.isEmpty(topic_tag)) {
topic_tag =TOPIC_TAG;
}
topic_person = typedArray.getString(R.styleable.MDTopicEditTextView_topic_person);
if(TextUtils.isEmpty(topic_person)) {
topic_person =TOPIC_TAG;
}
topic_text_color = typedArray.getColor(R.styleable.MDTopicEditTextView_topic_text_color,TOPIC_TEXT_COLOR);
topic_person_color = typedArray.getColor(R.styleable.MDTopicEditTextView_topic_person_color,TOPIC_PERSON_COLOR);
init();
}
private void init() {
//添加文本變化監(jiān)聽
this.addTextChangedListener(this);
}
public void setTopic(String topic){
setTopic(topic,TOPIC_TYPE_TOPIC); //默認(rèn)為話題標(biāo)簽
}
/**
* 添加話題
* @param topic 話題文本
*/
public void setTopic(String topic,int type){
if(TextUtils.isEmpty(topic)){
return;
}
String tagTopic ="";
if(type ==TOPIC_TYPE_TOPIC) {
tagTopic =topic_tag + topic +topic_tag; //話題前后添加標(biāo)簽符號("#topic#")
}else if(type ==TOPIC_TYPE_PERSON){
tagTopic =topic_person + topic; //話題前后添加標(biāo)簽符號("@topic")
}
topicList.add(tagTopic);
//獲取當(dāng)前光標(biāo)的位置
int selectionStart = getSelectionStart();
//獲取EditText上的文本內(nèi)容
Editable editable = getText();
if(selectionStart >=0){
// 插入話題
editable.insert(selectionStart,tagTopic+" ");
//移動光標(biāo)到最后
setSelection(getSelectionStart());
reFreshText(tagTopic);
}
setOnKeyListener(this);
}
/**
* 刷新UI,設(shè)置話題標(biāo)簽字體變色
* @param tagTopic
*/
private void reFreshText(String tagTopic) {
if (topicList.size() ==0)
return;
// 重新設(shè)置span
Editable editable = getText();
int textLength = editable.length();
int findPosition =0;
for (int i =0; I
String objectText =topicList.get(i);
while (findPosition <= textLength) {
// 獲取文本開始下標(biāo)
findPosition = getText().toString().indexOf(objectText, findPosition);
if (findPosition != -1) {
// 設(shè)置話題內(nèi)容前景色高亮
ForegroundColorSpan colorSpan;
if(objectText.startsWith(topic_tag))
colorSpan=new ForegroundColorSpan(topic_text_color);
else
colorSpan=new ForegroundColorSpan(topic_person_color);
editable.setSpan(colorSpan, findPosition, findPosition + objectText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
findPosition += objectText.length();
}else {
break;
}
}
}
}
/**
* 光標(biāo)改變監(jiān)聽
* @param selStart
* @param selEnd
*/
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd);
if(topicList ==null ||topicList.size() ==0){
return;
}
int startPositon =0;
int endPositon =0;
String topicText ="";
if(!isBack) {
for (int i =0; I
topicText =topicList.get(i);
int length = getText().toString().length();
startPositon = getText().toString().indexOf(topicText, startPositon);
endPositon = startPositon + topicText.length();
if (startPositon == -1) {
return;
}
if (selStart > startPositon && selEnd <= endPositon-1) {
if ((endPositon +1) > length) {
setSelection(endPositon);
}else {
setSelection(endPositon +1);
}
}
startPositon = endPositon;
}
}
isBack =false;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editablede) {
}
/**
* 鍵盤back鍵監(jiān)聽
* @param v
* @param keyCode
* @param event
* @return
*/
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
//返回鍵導(dǎo)致光標(biāo)的移動
isBack =true;
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
//如果光標(biāo)起始和結(jié)束在同一位置,說明是選中效果,直接返回 false 交給系統(tǒng)執(zhí)行刪除動作
if (selectionStart != selectionEnd) {
if(index != -1) {
topicList.remove(index);
index = -1;
}
return false;
}
Editable editable = getText();
String content = editable.toString();
int lastPos =0;
//遍歷判斷光標(biāo)的位置
for (int i =0; I
String topic =topicList.get(i);
lastPos = content.indexOf(topic, lastPos);
if (lastPos != -1) {
if (selectionStart !=0 && selectionStart > lastPos && selectionStart <= (lastPos + topic.length())) {
//選中話題
setSelection(lastPos, lastPos + topic.length());
index = I;
return true;
}
}
lastPos += topic.length();
}
}
return false;
}
}
在xml中 直接使用就行啦:
<com.modian.framework.ui.view.MDTopicEditTextView
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:topic_text_color="#A128CE" 話題標(biāo)簽顏色
app:topic_person_color="#E18A21" @某人 標(biāo)簽的顏色
app:topic_tag="6" 話題標(biāo)簽字符
app:topic_person="Y"/> @某人字符
來幾張效果圖:
image.png