Android 中的社交媒体用户标签





5.00/5 (2投票s)
在您的 Android 应用程序中实现用户标记。
引言
我最近在 Android 应用程序中添加了标记用户的功能。 如果您曾经在 Instagram 中标记过用户,您会发现当您输入“@
”符号时会得到一个用户列表,并且该列表会随着您输入字符而进行过滤,最终缩小用户列表的范围以供选择。 这是我能够在自己的应用程序中复制的基本行为,我想在此处在 CodeProject 上分享。
背景
我不会详细介绍后端 Web 服务,而是专注于 Android 实现。 基本上,我希望能够在我输入“@
”符号时调用用户列表。 然后,我想在输入我标记的用户名中的每个字符时继续过滤列表。 我还希望能够链接被标记的用户名,并在用户点击标签时显示用户个人资料页面。
Using the Code
让我们从活动布局文件开始。 我们需要一个 EditText
控件,供用户输入一些文本。 我更喜欢使用 RealtiveLayout
。 在 EditText
控件下方,我们有一个 ListView
控件,其可见性设置为“gone”,并且 width
和 height
设置为“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
”作为 width
和 height
值,将使其覆盖布局中的所有其他控件。 在这一点上,我假设您已经使用过 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
中设为可点击状态。 再次,我们将使用 Pattern
和 Matcher
类来查找我们的标签。 ClickableSpan
类用于使文本的子字符串可点击。 当我们找到用户标签的模式匹配时,我们会创建 clickableSpan
类的实例,重写 onClick
方法。 在此示例中,我们正在创建一个 Intent,该 Intent 将传递用户的友好名称(不包括“@
”字符)到我们的用户个人资料活动。 同样,我不会介绍 Intent 以及在活动之间传递值。 此代码段很可能位于将数据记录绑定到 ListView
的 Adapter
类中。 当用户滚动 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);
}
关注点
要记住的主要事情是使用 Pattern
、Matcher
和 ClickableSpan
类来查找用户标签,无论是在用户提交新帖子/回复时还是在用户阅读另一个用户发布的文本时。 重写 ClickableSpan
中的 onClick
方法允许您指定在用户点击用户标签时要采取的操作。 就我而言,导航到显示用户个人资料的活动。 另一个技巧是将数据存储为后端的编码 HTML,这允许您支持表情符号!
历史
- 2018 年 6 月 24 日:初始版本