65.9K
CodeProject 正在变化。 阅读更多。
Home

Android 中的社交媒体用户标签

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2018年6月24日

CPOL

3分钟阅读

viewsIcon

9600

在您的 Android 应用程序中实现用户标记。

引言

我最近在 Android 应用程序中添加了标记用户的功能。 如果您曾经在 Instagram 中标记过用户,您会发现当您输入“@”符号时会得到一个用户列表,并且该列表会随着您输入字符而进行过滤,最终缩小用户列表的范围以供选择。 这是我能够在自己的应用程序中复制的基本行为,我想在此处在 CodeProject 上分享。

背景

我不会详细介绍后端 Web 服务,而是专注于 Android 实现。 基本上,我希望能够在我输入“@”符号时调用用户列表。 然后,我想在输入我标记的用户名中的每个字符时继续过滤列表。 我还希望能够链接被标记的用户名,并在用户点击标签时显示用户个人资料页面。

Using the Code

让我们从活动布局文件开始。 我们需要一个 EditText 控件,供用户输入一些文本。 我更喜欢使用 RealtiveLayout。 在 EditText 控件下方,我们有一个 ListView 控件,其可见性设置为“gone”,并且 widthheight 设置为“match_parent”。 这是关键,因为我们发现一个用户标签会使 ListView 可见,并且它会填充屏幕,允许用户选择一个要标记的用户。

<EditText android:id="@+id/myEditText" android:layout_width="match_parent"	
android:layout_height="wrap_content" android:inputType="textMultiLine" android:minLines="5" 
android:maxLines="5" />
	
<ListView android:id="@+id/myUsers" android:layout_width=&"match_parent"	
android:layout_height="match_parent" android:divider="#E6E6E6" android:dividerHeight="2dip" 
android:paddingLeft="20dip" android:paddingRight="20dip" android:visibility="gone" 
android:background="#ffffff"/>

接下来,在 EditText 控件的 addTextChangedListener 中附加一个 TextWatcher。 在 TextWatcher 类中,当用户在 EditText 控件中输入时,“afterTextChanged”方法将触发,传递我们来自 EditText 控件的可编辑参数。 我们使用正则表达式查找在“@”字符后的字母数字 string,包括“-”和“.”字符。 我们不允许空格或其他特殊字符。 仅从光标的当前位置开始执行匹配很重要。 这将允许在 EditText 控件内使用多个标签。 一旦找到当前标签,您就需要获取子字符串(不包括“@”)并将其作为参数传递给您的后端服务,这将返回一个用户列表。 这也是您希望将 ListView 的可见性设置为 VISIBLE 的地方。 在 Relative 布局中,将 ListView 放在底部并将“match_parent”作为 widthheight 值,将使其覆盖布局中的所有其他控件。 在这一点上,我假设您已经使用过 ListView、适配器、通过滚动监听器分页等。

this.mEditText.addTextChangedListener(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 editable)
    {
        String text = editable.toString();
        Pattern p = Pattern.compile("[@][a-zA-Z0-9-.]+");
        Matcher m = p.matcher(text);
        int cursorPosition = mEditText.getSelectionStart();
        while(m.find())
        {
            if (cursorPosition >= m.start() && cursorPosition <= m.end())
            {
                final int s = m.start() + 1; // add 1 to ommit the "@" tag
                final int e = m.end();
	    		loadUsersFromBackEnd(text.substring(s, e);
                break;
            }
        }
    }
}); 

接下来,让我们来介绍一下相反的情况。 您正在查看另一个用户的帖子或评论,我们希望找到标签并将它们在 TextView 中设为可点击状态。 再次,我们将使用 PatternMatcher 类来查找我们的标签。 ClickableSpan 类用于使文本的子字符串可点击。 当我们找到用户标签的模式匹配时,我们会创建 clickableSpan 类的实例,重写 onClick 方法。 在此示例中,我们正在创建一个 Intent,该 Intent 将传递用户的友好名称(不包括“@”字符)到我们的用户个人资料活动。 同样,我不会介绍 Intent 以及在活动之间传递值。 此代码段很可能位于将数据记录绑定到 ListViewAdapter 类中。 当用户滚动 ListView 内容时,用户标签将显示为超链接。 单击它们将执行 ClickableSpan onClick 方法。

Pattern p = Pattern.compile("[@][a-zA-Z0-9-.]+");
Matcher m = p.matcher(ss);

while(m.find())
{
    final int s = m.start() + 1; // add 1 to omit the "@" tag
    final int e = m.end();

    ClickableSpan clickableSpan = new ClickableSpan()
    {
        @Override
        public void onClick(View textView)
        {
            Intent intent = new Intent(mContext, com.myawesomeapp.UserActivity.class);
            intent.putExtra(UserActivity.EXTRA_FRIENDLY_NAME, wallPost.getMessage().substring(s, e));
            mContext.startActivity(intent);
        }
    };

    ss.setSpan(clickableSpan, m.start(), m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

关注点

要记住的主要事情是使用 PatternMatcherClickableSpan 类来查找用户标签,无论是在用户提交新帖子/回复时还是在用户阅读另一个用户发布的文本时。 重写 ClickableSpan 中的 onClick 方法允许您指定在用户点击用户标签时要采取的操作。 就我而言,导航到显示用户个人资料的活动。 另一个技巧是将数据存储为后端的编码 HTML,这允许您支持表情符号!

历史

  • 2018 年 6 月 24 日:初始版本
© . All rights reserved.