创建具有类似标签功能的自定义 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 的相关文章

  • 如何获取之前的碎片?

    为了在我的应用程序中重用某些片段 我需要知道哪个片段是返回堆栈上的第二个片段 为了做到这一点 我正在使用getFragmentManager getFragments 显示以下错误 但有效 FragmentManager getFragme
  • 使用 google Directions API 的地图视图绘制方向 - 解码折线

    我正在尝试使用 Google 方向 API 在我的地图视图上显示方向 但我在从 JSON 响应获取数据时遇到困难 我可以获得 级别 和 点 字符串 但无法弄清楚如何将它们解码为地图上的点 任何帮助将非常感激 我有一个类可以为您解码它们 添加
  • Manifest Merger工具:替换失败

    我正在使用一个使用自己的 android theme 的库 因此在构建时收到以下错误 错误 55 9 任务 contacit processDebugManifest 执行失败 清单合并失败 AndroidManifest xml 中的属性
  • 安卓定位不准确

    我正在尝试获取当前用户的位置 我试图重构我的代码以获得更好的结果 但我只是不断得到关于准确度的荒谬位置 它在 900 600 米之间 如何才能得到更好的结果 使其精度达到50m以内 这是我的代码 package com agam mapsl
  • Android 如何更改 OnTouchListener 上的按钮背景

    你好 我在 xml 中有一个按钮 我正在使用OnTouchListener在我的活动中获得button按下并释放 但问题是 当我按下按钮时背景颜色没有改变 当我延长可能的活动时OnClickListener背景正在改变 任何人都可以告诉我的
  • 播放 SoundCloud 曲目

    我可以在 Android 应用程序中播放 SoundCloud 中的曲目吗 我正在尝试这段代码 但它不起作用 String res https api soundcloud com tracks 84973999 stream client
  • 如何解决 Firebase AuthUi 中无法找到显式活动?

    使用 firebase UI 时 我无法找到显式活动类 com firebase ui auth KickoffActivity protected void onCreate Bundle savedInstanceState super
  • 如何在android线性布局上获得阴影? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在android中为View设置阴影 https stackoverflow com questions 4406524 how to set shadow to a view in androi
  • Android 自定义布局 - onDraw() 永远不会被调用

    public class MainActivity extends Activity Override public void onCreate Bundle savedInstanceState super onCreate savedI
  • 使用 Retrofit2 和 Mockito 或 Robolectric 进行 Android 单元测试

    我可以测试 Retrofit2beta4 的真实响应吗 我需要 Mockito 或 Robolectic 吗 我的项目中没有活动 它将是一个库 我需要测试服务器是否正确响应 现在我有这样的代码并卡住了 Mock ApiManager api
  • AudioTrack、SoundPool 或 MediaPlayer,我应该使用哪个?

    如果我需要能够 播放多个音频文件 具有不同的持续时间 例如 5 到 30 秒 独立设置右 左声道的音量 应用声音效果 如混响 失真 那么 我应该使用哪个 API 另外 我在 AudioTrack API 上找不到太多文档 有谁知道在哪里可以
  • 如何在手机缓存中保存用户名和密码

    我有一个用户登录应用程序 它需要用户的电子邮件和密码 我想将电子邮件和密码保存在手机缓存中 以便用户不必再次输入 有什么办法可以将数据保存在Android缓存中吗 我认为你需要使用SharedPreference用于在设备中使用应用程序时保
  • 使用 PhoneGap 使 Android 应用程序易于访问(对于残障人士)

    有人有过使用 PhoneGap 使 Android 应用程序可访问的经验吗 至少我们需要使我们的应用程序符合第 508 条规定 我尝试实现一些标准的辅助功能 文本框标签 向 div 添加标题属性等 但是 当在 Android 中使用 Tal
  • Android FragmentTransaction 自定义动画(未知动画师名称:Translate)

    我正在尝试让自定义动画与我的片段一起使用 我已按照在线教程进行操作 但出现以下错误 java lang RuntimeException 未知的动画师名称 翻译 动画的 XML 如下
  • Android 后台服务示例,具有交互式调用方法

    我不是 Android 方面的专家 我正在寻找一个 Android 应用程序的示例 该应用程序使用一个服务 其中有真正的功能方法 或者换句话说 一个服务可以用来做什么 我们什么时候需要它 超越简单的东西服务举例 我确信您渴望获得一些工作代码
  • java.lang.NumberFormatException: Invalid int: "3546504756",这个错误是什么意思?

    我正在创建一个 Android 应用程序 并且正在从文本文件中读取一些坐标 我在用着Integer parseInt xCoordinateStringFromFile 将 X 坐标转换为整数 Y 坐标的转换方法相同 当我运行该应用程序时
  • 按钮 - 单击时更改背景颜色

    我的活动中有 8 个按钮 我正在寻找的是 按钮具有默认背景 单击按钮时 背景颜色应更改为其他颜色 这部分非常简单 但是 当我单击任何其他按钮时 第一个按钮的背景颜色应该变回默认颜色 我知道这将使用 选择器状态 来完成 但我不太确定如何实现它
  • Android:RecyclerView 不显示片段中的列表项

    有人可以帮我尝试让我的 RecyclerView 出现吗 如果我不在片段中实现它 就会出现这种情况 然而 当我尝试将其实现到片段中时 CarFront 中的其他 XML 代码与 RecyclerView 分开显示 我的日志中收到此错误 E
  • 在 KitKat 4.4.2 中获取 SDard 路径和大小

    我在 Google Play 上有一个设备信息应用程序 在该应用程序中我有存储信息 我知道 Android 4 4 在访问外部 SD 卡方面发生了一些变化 内部似乎没有给我带来问题 我的问题是 如何可靠地获取 KitKat 上 SD 卡的大
  • Android:AsyncTask ProgressDialog 将不会在 ActivityGroup 中打开

    我试图在轮询我的服务器时打开一个进度对话框 该类是一个 ActivityGroup 因为它嵌套在选项卡栏中 为了将视图保持在框架内 需要 ActivityGroup 这是我的 ActivityGroup 类的声明 public class

随机推荐

  • 从特定于语言环境的字符串获取 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