Android仿微信@好友功能 輸入@跳轉(zhuǎn)、刪除整塊
最近在做聊天功能的時(shí)候,有一個(gè)需求是仿照微信做@好友的功能,本來(lái)以為挺簡(jiǎn)單,但是做到這塊的時(shí)候,發(fā)現(xiàn)和想象的有點(diǎn)不一樣,什么整塊刪除,塊可編輯,總之,加個(gè)@的功能很簡(jiǎn)單,但是要做和微信的一樣還是費(fèi)了一些功夫,下面是一個(gè)demo僅供參考,防止遺忘
先上個(gè)效果圖
就是這么個(gè)功能
1. 分析需求
輸入@跳轉(zhuǎn)到聯(lián)系人界面,選中一個(gè)或者多個(gè)好友返回到當(dāng)前界面
按退格鍵刪除整塊內(nèi)容
塊內(nèi)的內(nèi)容可編輯,編輯完了之后將不附帶@功能,只是單純的文字
2. 開(kāi)始編碼
既然是文本輸入首先繼承EditText自定義一個(gè)控件
public class MsgEditText extends AppCompatEditText { public MsgEditText(Context context) { super(context); } public MsgEditText(Context context, AttributeSet attrs) { super(context, attrs); } public MsgEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
到底從哪里開(kāi)始入手呢,首先完成變成塊的需求,
無(wú)意中看到這個(gè)項(xiàng)目https://github.com/g707175425/CloudEditText ,他是這么寫的
private void generateOneSpan(Spannable spannableString, UnSpanText unSpanText) { //生成一個(gè)TextView View spanView = getSpanView(getContext(), unSpanText.showText.toString(), getMeasuredWidth()); //再將TextView轉(zhuǎn)換為一個(gè)圖片 BitmapDrawable bitmpaDrawable = (BitmapDrawable) UIUtils.convertViewToDrawable(spanView); bitmpaDrawable.setBounds(0, 0, bitmpaDrawable.getIntrinsicWidth(), bitmpaDrawable.getIntrinsicHeight()); //最后將這個(gè)圖片放到Span里, MyImageSpan what = new MyImageSpan(bitmpaDrawable, unSpanText.showText.toString(),unSpanText.returnText); final int start = unSpanText.start; final int end = unSpanText.end; spannableString.setSpan(what, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //設(shè)置一個(gè)Span spannableString.setSpan(touchableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); }
看到這里我們就記得了一個(gè)關(guān)于SpanableString的用法,它可以設(shè)置圖片,可以隨意的設(shè)置文字的背景的前景,等等一系列比較酷炫的效果,而且只需要一個(gè)TextView,如果需要深入了解Span,可自行百度和Google,關(guān)于Span的進(jìn)階用法,于是就有了下面的實(shí)現(xiàn)
//這個(gè)是需要成塊刪除的內(nèi)容 private class MyTextSpan extends MetricAffectingSpan { private String showText; private long userId; //userId是為了適應(yīng)需求,如果不需要請(qǐng)自行去掉 public MyTextSpan(String showText, long userId) { this.showText = showText; this.userId = userId; } public String getShowText() { return showText; } public long getUserId() { return userId; } @Override public void updateMeasureState(TextPaint p) { } @Override public void updateDrawState(TextPaint tp) { } } //這個(gè)是非整塊刪除的內(nèi)容,當(dāng)然你如果想也是可以刪除的 private class UnSpanText { int start; int end; String returnText; UnSpanText(int start, int end, String returnText) { this.start = start; this.end = end; this.returnText = returnText; } }
剛開(kāi)始我是這么寫的
//外部調(diào)用一個(gè)增加Span的方法 public void addSpan(String showText, String returnText, long userId) { getText().append(showText); SpannableString spannableString = new SpannableString(getText()); makeSpan(spannableString, new UnSpanText(spannableString.length() - showText.length(), spannableString.length(), showText, returnText), userId); setText(spannableString); setSelection(spannableString.length()); } //生成一個(gè)需要整體刪除的Span private void makeSpan(Spannable sps, UnSpanText unSpanText, long userId) { MyTextSpan what = new MyTextSpan(unSpanText.returnText, userId); int start = unSpanText.start; int end = unSpanText.end; sps.setSpan(what, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); }
寫到現(xiàn)在這個(gè)整塊添加已經(jīng)做好了,下面開(kāi)始做整塊刪除,剛開(kāi)始的時(shí)候我是模仿上面的CloudEditText寫的,但我發(fā)現(xiàn)好像會(huì)用各種問(wèn)題,于是想了一種方法
@Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); //向前刪除一個(gè)字符,@后的內(nèi)容必須大于一個(gè)字符,可以在后面加一個(gè)空格 if (lengthBefore == 1 && lengthAfter == 0) { MyTextSpan[] spans = getText().getSpans(0, getText().length(), MyTextSpan.class); for (MyTextSpan myImageSpan : spans) { if (getText().getSpanEnd(myImageSpan) == start && !text.toString().endsWith(myImageSpan.getShowText())) { getText().delete(getText().getSpanStart(myImageSpan), getText().getSpanEnd(myImageSpan)); break; } } } }
上面的意思就是,如果你在EditText中執(zhí)行刪除一個(gè)字符的時(shí)候,判斷前面一個(gè)是否是一個(gè)Span,如果是自定義的Span就把Span一同刪除,關(guān)于這個(gè),我可是測(cè)試可各種操作才定為這樣的
最后是獲取需要@的人員名單
//獲取用戶Id列表,這只是個(gè)參考,可根據(jù)需求修改 public String getUserIdString() { MyTextSpan[] spans = getText().getSpans(0, getText().length(), MyTextSpan.class); StringBuilder builder = new StringBuilder(); for (MyTextSpan myTextSpan : spans) { String realText = getText().toString().substring(getText().getSpanStart(myTextSpan), getText().getSpanEnd(myTextSpan)); String showText = myTextSpan.getShowText(); if (realText.equals(showText)) { builder.append(myTextSpan.getUserId()).append(","); } } if (!TextUtils.isEmpty(builder.toString())) { builder.deleteCharAt(builder.length() - 1); } return builder.toString(); }
最后我就大方的放個(gè)地址你們自己看吧
https://github.com/ddssingsong/AtFriend
總結(jié)
以上所述是小編給大家介紹的Android仿微信@好友功能 輸入@跳轉(zhuǎn)、刪除整塊,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
很詳細(xì)的android序列化過(guò)程Parcelable
這篇文章主要為大家詳細(xì)介紹了很詳細(xì)的android序列化過(guò)程Parcelable,代碼注釋很詳細(xì),感興趣的小伙伴們可以參考一下2016-08-08解決Android Studio電腦不支持HAXM的問(wèn)題
這篇文章主要介紹了Android Studio電腦不支持HAXM的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-03-03android開(kāi)發(fā)基礎(chǔ)教程—文件存儲(chǔ)功能實(shí)現(xiàn)
文件存儲(chǔ)功能在實(shí)現(xiàn)數(shù)據(jù)讀寫時(shí)會(huì)頻繁使用到,接下來(lái)介紹文件存儲(chǔ)功能的實(shí)現(xiàn),感興趣的朋友可以了解下2013-01-01android自定義等級(jí)評(píng)分圓形進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了android自定義等級(jí)評(píng)分圓形進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07