2018-11-26 仿抖音发布页@好友功能 点击删除键直接删除整个字段数据

写在前面:
最近心态有点暴

工程项目中,有个功能,发布功能,发布View可以选择@好友列表进行对应格式显示,直接上图


2018-11-26 仿抖音发布页@好友功能 点击删除键直接删除整个字段数据_第1张图片

效果就是类似这个了。选择好友后,回调过来直接在页面显示对应格式、并且点击删除按钮,直接删除刚才的完整@好友的字段(注意,不是一个个文字删除)

好了。直接上源码:

 * Desc:@联系人 整块删除 不可编辑
 * 

* Author: * Date: 2018-09-13 * Copyright: Copyright (c) 2010-2018 * Company: * Updater: * Update Time: * Update Comments: */ public class ContactEditText extends AppCompatAutoCompleteTextView { private int itemPadding; private String content = ""; public ContactEditText(Context context) { super(context); init(); } public ContactEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ContactEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { itemPadding = dip2px(getContext(), 3); } @Override protected void onSelectionChanged(int selStart, int selEnd) { MyImageSpan[] spans = getText().getSpans(0, getText().length(), MyImageSpan.class); for (MyImageSpan myImageSpan : spans) { if (getText().getSpanEnd(myImageSpan) - 1 == selStart) { selStart = selStart + 1; setSelection(selStart); break; } } super.onSelectionChanged(selStart, selEnd); } private void flushSpans() { Editable editText = getText(); Spannable spannableString = new SpannableString(editText); MyImageSpan[] spans = spannableString.getSpans(0, editText.length(), MyImageSpan.class); List texts = getAllTexts(spans, editText); for (UnSpanText unSpanText : texts) { if (!TextUtils.isEmpty(unSpanText.showText.toString().trim())) { generateOneSpan(spannableString, unSpanText); } } setText(spannableString); setSelection(spannableString.length()); } private List getAllTexts(MyImageSpan[] spans, Editable edittext) { List texts = new ArrayList<>(); int start; int end; CharSequence text; List sortStartEnds = new ArrayList<>(); sortStartEnds.add(0); for (MyImageSpan myImageSpan : spans) { sortStartEnds.add(edittext.getSpanStart(myImageSpan)); sortStartEnds.add(edittext.getSpanEnd(myImageSpan)); } sortStartEnds.add(edittext.length()); Collections.sort(sortStartEnds); for (int i = 0; i < sortStartEnds.size(); i = i + 2) { start = sortStartEnds.get(i); end = sortStartEnds.get(i + 1); text = edittext.subSequence(start, end); if (!TextUtils.isEmpty(text)) { // TODO: 2018/9/13 这里的ID为测试id texts.add(new UnSpanText(start, end, text, "-1")); } } return texts; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) { // flushSpans();//文字转换成图片块 这里是自动联想的功能,可根据需求进行添加 return true; } return super.onKeyDown(keyCode, event); } @Override protected void performFiltering(CharSequence text, int keyCode) { Log.d("dds", "performFiltering" + text + ":" + keyCode); super.performFiltering(text, keyCode); } //添加一个Span public void addSpan(PatRecordUserBean userBean) { String showText = userBean.getUserName(); String showId = userBean.getUserId(); getText().append(showText); SpannableString spannableString = new SpannableString(getText()); generateOneSpan(spannableString, new UnSpanText(spannableString.length() - showText.length(), spannableString.length(), showText, showId)); setText(spannableString); setSelection(spannableString.length()); } public void insertSpan(PatRecordUserBean userBean) {//根据位置插入 String showText = userBean.getUserName(); String showId = userBean.getUserId(); Editable editable = getText(); int start = getSelectionStart(); int end = start + showText.length(); editable.insert(start, showText); SpannableString spannableString = new SpannableString(getText()); generateOneSpan(spannableString, new UnSpanText(start, end, showText, showId)); setText(spannableString); setSelection(end); } public void insertText(String insertData) {//插入文案信息 if (null != insertData) { CharSequence charSequence = insertData; Editable editable = getText(); int start = getSelectionStart(); int end = start + charSequence.length(); editable.insert(start, charSequence); } } private void generateOneSpan(Spannable spannableString, UnSpanText unSpanText) { //文字转图片 View spanView = getSpanView(getContext(), unSpanText.showText.toString(), getMeasuredWidth()); BitmapDrawable bitmapDrawable = (BitmapDrawable) convertViewToDrawable(spanView); bitmapDrawable.setBounds(0, 0, bitmapDrawable.getIntrinsicWidth(), bitmapDrawable.getIntrinsicHeight()); MyImageSpan what = new MyImageSpan(bitmapDrawable, unSpanText.showText.toString(), unSpanText.showId); final int start = unSpanText.start; final int end = unSpanText.end; spannableString.setSpan(what, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } public Drawable convertViewToDrawable(View view) { int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); view.measure(spec, spec); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); c.translate(-view.getScrollX(), -view.getScrollY()); view.draw(c); view.setDrawingCacheEnabled(true); Bitmap cacheBmp = view.getDrawingCache(); Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true); cacheBmp.recycle(); view.destroyDrawingCache(); return new BitmapDrawable(viewBmp); } public View getSpanView(Context context, String text, int maxWidth) { TextView view = new TextView(context); // view.setMaxWidth(maxWidth); // view.setText(text); // view.setEllipsize(TextUtils.TruncateAt.END); // view.setSingleLine(true); view.setText(text); //设置文字框背景色 // view.setBackgroundResource(R.drawable.shape_corner_rectangle); //view.setBackgroundResource(R.drawable.shape_corner_rectangle); view.setTextSize(getTextSize()); //设置文字颜色 //view.setTextColor(getCurrentTextColor()); view.setTextColor(Color.WHITE); FrameLayout frameLayout = new FrameLayout(context); frameLayout.setPadding(itemPadding, itemPadding, itemPadding, itemPadding); frameLayout.addView(view); return frameLayout; } private class UnSpanText implements Serializable { int start; int end; CharSequence showText; String showId; UnSpanText(int start, int end, CharSequence showText, String showId) { this.start = start; this.end = end; this.showText = showText; this.showId = showId; } } public class MyImageSpan extends ImageSpan implements Serializable { private String showText; public String getShowId() { return showId; } public void setShowId(String showId) { this.showId = showId; } private String showId; public MyImageSpan(Drawable d, String showText, String showId) { super(d); this.showText = showText; this.showId = showId; } public String getShowText() { return showText; } } /** * dip转换px */ public static int dip2px(Context context, int dip) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dip * scale + 0.5f); } public void resumeSpanText(String oldString, ArrayList str) {//恢复草稿标题数据 int contentStart = 0; int contentEnd; int tmpCutStart; int tmpCutEnd; if (str.size() == 0) { insertText(oldString); return; } for (int i = 0; i < str.size(); i++) { Matcher matcher = matchStringByRegularExpression(oldString, str.get(i).getUserName()); if (matcher != null) { int start = matcher.start(); int end = matcher.end(); contentEnd = start;//裁剪的结尾 content = oldString.substring(contentStart, contentEnd); contentStart = end; Log.d("数据", ">>>>" + start + ">>>" + end + ">>>" + content); if (!TextUtils.isEmpty(content)) { insertText(content); } addSpan(str.get(i)); } } if (getText().length() < oldString.length()) { String substring = oldString.substring(getText().length(), oldString.length()); if (!TextUtils.isEmpty(substring)) { insertText(substring); } } } public static Matcher matchStringByRegularExpression(String parent, String child) { Pattern p = Pattern.compile(child); Matcher m = p.matcher(parent); while (m.find()) { return m; } return null; } public ArrayList getFinalSpan() {//获取最终的@好友的用户Bean数据 ArrayList patRecordUserBeans = new ArrayList<>(); Editable editText = getText();//这里不能使用toString()。否则格式会被重置。 Spannable spannableString = new SpannableString(editText); MyImageSpan[] spans = spannableString.getSpans(0, editText.length(), MyImageSpan.class); if (spans == null || spans.length == 0) { return patRecordUserBeans; } else { for (int i = 0; i < spans.length; i++) { PatRecordUserBean bean = new PatRecordUserBean(); bean.setUserId(spans[i].getShowId()); bean.setUserName(spans[i].getShowText()); patRecordUserBeans.add(bean); } return patRecordUserBeans; } } }

实体类

/**
 * Desc:@好友功能实体类
 * 

* Author: * Date: 2018-09-13 * Copyright: Copyright (c) 2010-2018 * Company: * Updater: * Update Time: * Update Comments: */ public class PatRecordUserBean implements Serializable { private String userId; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } private String userName; }

知道你们不喜欢看源码,直接看用法吧
1.当前页面有保存草稿功能,如果需要恢复上一次的草稿数据,直接调用

 ArrayList oldUserBean = draftPatRecordParamJson.getUserSpan();
     if (oldUserBean != null) {
           editTitle.resumeSpanText(videoTitle, oldUserBean);
         } 

2.设置监听、我这里是最大只能60个字符

editTitle.addTextChangedListener(new TextWatcher() {
            private CharSequence temp;
            private int starts, end;
            private int deleteIndex;

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int lengthBefore, int lengthAfter) {
                temp = s;
                if (lengthAfter == 1 && "@".equals(String.valueOf(s.charAt(start))) && s.length() <= 60) {
                   //这里可以直接跳转选择好友的页面
                    editTitle.getText().delete(s.length() - 1, s.length());
                } else if (lengthBefore == 1 && lengthAfter == 0) {  //向前删除一个字符,@后的内容必须大于一个字符,可以在后面加一个空格
                }
            }

            @Override
            public void afterTextChanged(Editable s) {//变化
                if (temp.length() > 60) {
                    ToastUtils.showShort(R.string.patrecord_public_title_word_count);
                    s.delete(editTitle.getSelectionStart() - 1, editTitle.getSelectionStart());
                }
            }
        });

3.选择好友后、onActivityForResult进行数据显示

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PatRecordConstant.PatRecordParamsType.PAT_COVER) {
          if (resultCode == PatRecordConstant.PatRecordParamsType.PAT_FRIEND_CODE) {
                friendName = "@" + data.getStringExtra(PatRecordConstant.PatRecordParamsType.Pat_PUBLIC_FRIEND_NAME) + "";
                friendId = data.getStringExtra(PatRecordConstant.PatRecordParamsType.Pat_PUBLIC_FRIEND_NAME_ID) + "";
                ArrayList finalSpan = editTitle.getFinalSpan();
                for (int i = 0; i < finalSpan.size(); i++) {
                    PatRecordUserBean patRecordUserBean = finalSpan.get(i);
                    String userId = patRecordUserBean.getUserId();
                    if (!TextUtils.isEmpty(friendId) && userId.equals(friendId)) {
                        return;
                    }
                }
                if (editTitle.getText().length() + friendName.length() <= 60) {
                    PatRecordUserBean userBean = new PatRecordUserBean();
                    userBean.setUserName(friendName);
                    userBean.setUserId(friendId);
                    editTitle.insertSpan(userBean);//插入数据(@好友的数据)
               
                } else {
                    ToastUtils.showShort(R.string.patrecord_public_title_word_count);
                }
            } 
        }
    }

好了,我发现大家都一样,一般网上找解决方案。只要结果。不要过程的,其实我也一样。
但是总要学习,总要进步,毕竟家里没矿~~

有问题留言沟通,并且点个喜欢,点个收藏之类的,项目中有参考了其他同志的项目,因为写的有点久,这里我也找不出项目地址了。有介意的同志联系我

你可能感兴趣的:(2018-11-26 仿抖音发布页@好友功能 点击删除键直接删除整个字段数据)