创建具有类似标签功能的自定义 editText

2024-01-04

我一直在四处寻找,但找不到任何答案。我想要实现的是一个类似于 ICS gmail 应用程序撰写屏幕中的“收件人”字段的 EditText。

Here's an image describing what I want: enter image description here

我正在考虑延长EditText并实现我自己的习惯EditText类,但我不太确定如何做到这一点,或者即使这是最好的解决方案。有什么想法吗?


改编自的解决方案这个答案 https://stackoverflow.com/questions/10812316/contact-bubble-edittext/10864568#10864568。插入逗号时自动分隔输入(分隔符可以调整)。创建一个 ImageSpan 和一个 ClickableSpan(可以通过单击右侧部分删除条目)。

public class TagEditText extends EditText {

    TextWatcher textWatcher;

    String lastString;

    String separator = ",";

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


    private void init() {
        setMovementMethod(LinkMovementMethod.getInstance());

        textWatcher = new TextWatcher() {
            @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 s) {
                String thisString = s.toString();
                if (thisString.length() > 0 && !thisString.equals(lastString)) {
                    format();

                }
            }
        };

        addTextChangedListener(textWatcher);
    }


    private void format() {

        SpannableStringBuilder sb = new SpannableStringBuilder();
        String fullString = getText().toString();

        String[] strings = fullString.split(separator);


        for (int i = 0; i < strings.length; i++) {

            String string = strings[i];
            sb.append(string);

            if (fullString.charAt(fullString.length() - 1) != separator.charAt(0) && i == strings.length - 1) {
                break;
            }

            BitmapDrawable bd = (BitmapDrawable) convertViewToDrawable(createTokenView(string));
            bd.setBounds(0, 0, bd.getIntrinsicWidth(), bd.getIntrinsicHeight());

            int startIdx = sb.length() - (string.length());
            int endIdx = sb.length();

            sb.setSpan(new ImageSpan(bd), startIdx, endIdx, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            MyClickableSpan myClickableSpan = new MyClickableSpan(startIdx, endIdx);
            sb.setSpan(myClickableSpan, Math.max(endIdx-2, startIdx), endIdx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            if (i < strings.length - 1) {
                sb.append(separator);
            } else if (fullString.charAt(fullString.length() - 1) == separator.charAt(0)) {
                sb.append(separator);
            }
        }


        lastString = sb.toString();

        setText(sb);
        setSelection(sb.length());

    }

    public View createTokenView(String text) {


        LinearLayout l = new LinearLayout(getContext());
        l.setOrientation(LinearLayout.HORIZONTAL);
        l.setBackgroundResource(R.drawable.bordered_rectangle_rounded_corners);

        TextView tv = new TextView(getContext());
        l.addView(tv);
        tv.setText(text);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);

        ImageView im = new ImageView(getContext());
        l.addView(im);
        im.setImageResource(R.drawable.ic_cross_15dp);
        im.setScaleType(ImageView.ScaleType.FIT_CENTER);

        return l;
    }

    public Object convertViewToDrawable(View view) {
        int spec = View.MeasureSpec.makeMeasureSpec(0, View.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);
        view.destroyDrawingCache();
        return new BitmapDrawable(getContext().getResources(), viewBmp);
    }

    private class MyClickableSpan extends ClickableSpan{

        int startIdx;
        int endIdx;

        public MyClickableSpan(int startIdx, int endIdx) {
            super();
            this.startIdx = startIdx;
            this.endIdx = endIdx;
        }

        @Override
        public void onClick(View widget) {



            String s = getText().toString();

            String s1 = s.substring(0, startIdx);
            String s2 = s.substring(Math.min(endIdx+1, s.length()-1), s.length() );

            TagEditText.this.setText(s1 + s2);
        }

    }
}

R.drawable.bordered_rectangle_rounded_corners:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid
        android:color="@color/transparent"/>
    <stroke android:width="1dp" android:color="#AAAAAA" />
    <corners
        android:radius="100dp" />
    <padding
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp" />
</shape>

最后要添加的是“x-Button”的 png。到目前为止效果很好,唯一的问题是长按删除键不起作用(如果有人知道如何使其工作,请随时发表评论)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建具有类似标签功能的自定义 editText 的相关文章

随机推荐

  • 从特定于语言环境的字符串获取 NSDecimalNumber?

    我有一些特定于区域设置的字符串 例如 0 01 或 0 01 我想将此字符串转换为 NSDecimalNumber 来自到目前为止我在互联网上看到的例子 http developer apple com documentation Coco
  • WP8.1 InvokeScript 错误

    我正在开发 Windows Phone 8 1 应用程序 我对 WebBrowser 类的 InvokeScript 方法有疑问 我的 XAML 中有这个 当我运行这段代码时 myWebBrowser Loaded object sende
  • 从 ServletContext 资源解析 XML 文档 [/WEB-INF/applicationContext.xml];

    我在控制台中遇到一些错误 我将在下面发布 我正在使用 eclipse 并清理了项目 刷新了目标 清理了 tomcat 服务器 因此追逐或任何此类性质的事情都不是问题 控制台错误 SEVERE Context initialization f
  • 从 C# 获取 Windows 应用程序的位置

    我需要一些帮助来尝试获取记事本窗口的位置 我很确定我需要使用GetWindowRect功能如下 但我不知道如何使用它 我已将以下内容放入 win 表单项目中 但是myRect X myRect Y等里面没有任何东西 我认为他们至少应该有我正
  • webrtc:mediaDevices.enumerateDevices() 返回空 deviceId

    我目前正在探索 webRTC 我想做的是获取所有媒体设备信息以及deviceId using navigator mediaDevices enumerateDevices 然后根据其种类属性将其分离出来 并允许用户选择针对特定种类使用哪种
  • Python -- 正则表达式 -- 如何在两组字符串之间查找字符串

    考虑以下 div a href foo1 com Foo1 a div a href Home a div div a href extract Extract a div div a href sitemap Sitemap a div
  • Array.prototype.sort(compareFn) 在浏览器中的工作方式不同?

    我一直在测试作为回调给出的比较函数Array prototype sort compareFn 当compareFn返回value 0时 但我在Chrome中得到了意外的行为 Chrome 1 2 3 4 5 6 7 8 9 10 sort
  • 如何将后备样式属性应用到 React JS 组件?

    我想将后备样式属性应用于组件 例如 var inlineStyle display webkit box display webkit flex display moz box display moz flex display ms fle
  • 如何使用jenkins删除目录中的文件

    在我的系统中 我每天都会在 1 个文件夹中下载新版本 然后将其用于进一步的原因 但在运行 jenkins 作业后 我想删除该文件夹 不是工作区 中的文件 这将从同一目录中删除特定文件夹 这将帮助我每次根据同一台机器上运行的不同詹金斯作业下载
  • Swift:格式化字符串宽度

    我想做的事情在 C C Java 和许多其他语言中非常简单 我想要做的就是能够指定字符串的宽度 类似于 printf 15s var 这将创建 15 个字符的字段宽度 我已经做了很多谷歌搜索 我尝试过使用COpaquepointer也Str
  • 如何在 HTTP 请求中使用 urllib2 发送自定义标头?

    我想在使用 urllib2 urlopen 时在请求中发送自定义 Accept 标头 我怎么做 不完全的 创建一个Request对象实际上并不发送请求 并且 Request 对象没有Read 方法 还 read 是小写 您所需要做的就是通过
  • Strace 检测到对 brk 的调用,但 GDB 不会在断点处停止

    我已经尝试调试内存泄漏相当长一段时间了 我的主要问题是无法使用像 Valgrind 之类的正确工具 所以我选择了普通的 GDB strace 我的程序是一个循环 在每次迭代中 它都会创建一些对象 然后调用它们的析构函数 正如它所解释的her
  • 检测 Android 手机上的 5G 连接

    我正在尝试确定蜂窝连接的类型 我使用了不同的方法 例如建议的方法here https stackoverflow com a 55975119 987753 但结果是 我在配备 Android 10 和 5G 连接的三星设备上不断获得 4G
  • 在 EditText 小部件中显示默认日期

    如何在运行时动态显示 EditText 小部件文本中的当前日期 谢谢 帕特里克 如果您的 EditText 在 xml 文件中声明 则必须在代码中检索它 如下所示 EditText editText EditText findViewByI
  • 创建将在 Outlook 中打开的 mailto 超链接,并在正文中显示超链接

    这是我的场景 我正在尝试在使用 mailto 超链接生成的电子邮件正文中嵌入一个超链接 所以我会有这样的东西 a href Click Here to open Outlook and with generated email a 问题是
  • 确定按下哪个键

    javascript中如何判断按下的是哪个键 在接受关键事件的函数中 function e var key String fromCharCode e keyCode
  • 使 { 和 } 忽略仅包含空格的行

    当您使用 和 在 vi m 中按段落导航时 它会跳过只包含空格的行 尽管它们在其他情况下是 空白 我如何说服 vim 将 仅空白 行视为段落分隔符 以便 和 跳转到它们 这是正确处理计数的修改版本 function ParagraphMov
  • SnakeYaml 中的多态集合

    我的目的是使用 jackson 拥有像 JSON 中的多态集合 也许可以借助标签 我似乎无法正确配置它 我的 yaml 文件是 person age 27 job dev name me skills devSkill descriptio
  • 如何在Windows GUI中绘制垂直文本?

    我需要在我的本机 C Win32 GUI 应用程序中绘制一列垂直文本 日语 它是从上到下而不是从左到右绘制 我浏览了 MSDN 只找到了如何绘制从右到左的文本 除了单独绘制每个字符之外 如何输出从上到下的文本 直接的 Win32 API 无
  • 创建具有类似标签功能的自定义 editText

    我一直在四处寻找 但找不到任何答案 我想要实现的是一个类似于 ICS gmail 应用程序撰写屏幕中的 收件人 字段的 EditText Here s an image describing what I want 我正在考虑延长EditT