- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 RecyclerView CardView 的 SearchView 上设置了一个 Spannable。如果在 CardView 上找到用户输入的文本,该文本将以红色突出显示。清除 SearchView 行后,我希望 CardView 文本返回默认的黑色。目前,文本被清除并且颜色错误地保持为红色。我尝试在 TextView 上使用“removeSpan”,但没有成功。 TextView 是“cardBlankText2”。我在这里缺少什么?
RecyclerView Adapter file
private List<ListItem> mListItems;
...
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent,false);
final ItemHolder itemHolder = new ItemHolder(view);
return itemHolder;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
private TextView cardBlankText2;
private ItemHolder(View itemView) {
super(itemView);
cardBlankText2 = (TextView) itemView.findViewById(R.id.cardBlankText2);
}
public ForegroundColorSpan getForegroundColorSpan(){
return foregroundColorSpan;
}
}
public void setFilter(List<ListItem> listItems, String searchString) {
// Note: the String is to get s.toString() from the Main Activity SearchView.
// Note the plural for listItems.
mListItems = new ArrayList<>();
mListItems.addAll(listItems);
this.searchString = searchString;
notifyDataSetChanged();
}
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListItem listItem = mListItems.get(position);
String todoHighlight = listItem.getTodo().toLowerCase(Locale.getDefault());
String note1Highlight = listItem.getNote1().toLowerCase(Locale.getDefault());
// Set up the logic for the highlighted text
int todoStartPos = todoHighlight.indexOf(searchString);
int todoEndPos = todoStartPos + searchString.length();
int note1StartPos = note1Highlight.indexOf(searchString);
int note1EndPos = note1StartPos + searchString.length();
Spannable spanString2 = Spannable.Factory.getInstance().newSpannable(
itemHolder.cardBlankText2.getText());
if (todoStartPos != -1 && searchString.length() > 0 && todoHighlight.contains(searchString)) {
spanString2.setSpan(new ForegroundColorSpan(Color.RED), todoStartPos, todoEndPos,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
itemHolder.cardBlankText2.setText(spanString2);
}
**else if (searchString.length() == 0) {
spanString2.removeSpan(itemHolder.cardBlankText2.getText());
itemHolder.cardBlankText2.setText(spanString2);
}**
}
MainActivity
public class MainActivity extends AppCompatActivity {
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.cardview_menu, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
searchItem.setVisible(true);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
final EditText mSearchEditText = (EditText) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
mSearchEditText.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 s) {
final ArrayList<ListItem> filteredModelList2 = filter(allList, s.toString());
if (!mSearchView.isIconified() && filteredModelList2.size() == 0) {
// re-load the list so the Adapter refreshes the RecyclerView list View.
adapter.clear();
adapter.addAll(allList);
} else if (!mSearchView.isIconified() && filteredModelList2.size() > 0) {
adapter.setFilter(filteredModelList2, s.toString());
mRecyclerView.scrollToPosition(0);
}
});
return super.onCreateOptionsMenu(menu);
}
// Do Search filtering from MainActivity's OnQueryTextChange(String newText)
// The Spannable code is in the onBindVH section for the itemHolders.
public ArrayList<ListItem> filter(List<ListItem> listItems, String query) {
query = query.toLowerCase();
final ArrayList<ListItem> filteredModelList = new ArrayList<>();
for (ListItem listItem : listItems) {
final String text = listItem.getTodo().toLowerCase();
final String text2 = listItem.getNote1().toLowerCase();
final String text3 = listItem.getNote2().toLowerCase();
if (text.contains(query) || text2.contains(query) ||
text3.contains(query)) {
filteredModelList.add(listItem);
}
}
return filteredModelList;
}
最佳答案
removeSpan()
方法是 setSpan()
的反向操作,因此您应该将同一个对象传递给它们。为此,请将 ForegroundColorSpan
设为 ViewHolder
的一个字段(见下文)
public void onBindViewHolder(final MyViewHolder itemHolder, int position) {
String todoHighlight = mListItems.get(position).getTodo();
itemHolder.cardBlankText2.setText(todoHighlight);
// Set up the logic for the highlighted text
int todoStartPos = todoHighlight.indexOf(searchString);
int todoEndPos = todoStartPos + searchString.length();
// ... skipped some lines ...
Spannable spanString2 = Spannable.Factory.getInstance().newSpannable(
itemHolder.cardBlankText2.getText());
if (todoStartPos != -1 && searchString.length() > 0 && todoHighlight.contains(searchString)) {
spanString2.setSpan(itemHolder.getForegroundColorSpan(), todoStartPos, todoEndPos,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
itemHolder.cardBlankText2.setText(spanString2);
}
else if (searchString.length() == 0) {
spanString2.removeSpan(itemHolder.getForegroundColorSpan());
itemHolder.cardBlankText2.setText(spanString2);
}
}
ViewHolder:
class MyViewHolder extends RecyclerView.ViewHolder{
private ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
public MyViewHolder(View itemView){
super(itemView);
}
public ForegroundColorSpan getForegroundColorSpan(){
return foregroundColorSpan;
}
}
编辑远程调试很困难,所以让我们反过来做,MCVE 风格:请使用下面的代码,运行它,如果它有效(比如“根据搜索文本突出显示更改”),那么你就更进一步了道路。
public class Activity8_RecyclerViewGrid extends AppCompatActivity
{
private int counter = 0;
private static String[] searchTexts = new String[]{"rem", "ia", "", "ol" };
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity8__recycler_view);
RecyclerView rcv = (RecyclerView)findViewById(R.id.recyclerView);
rcv.setLayoutManager(new GridLayoutManager(this, 2));
final MyAdapter adapter = new MyAdapter(allMyWords());
rcv.setAdapter(adapter);
final TextView tvSearchText = (TextView)findViewById(R.id.tvSearchText);
Button btnFilter = (Button)findViewById(R.id.btnFilter);
btnFilter.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
String searchString = searchTexts[counter%4];
adapter.setFilter(Activity7_GridViewStuff.allMyBooks(), searchString);
tvSearchText.setText(searchString);
counter++;
}
});
}
public static ArrayList<String> allMyWords()
{
String[] theLoremArray = null;
String LOREM_STRING = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";
String[] sTemp = LOREM_STRING.split(" ");
StringBuilder sb = new StringBuilder();
theLoremArray = new String[sTemp.length/3];
for (int i = 0; i < (sTemp.length - sTemp.length%3); i++)
{
sb.append(sTemp[i]).append(" ");
if (i%3 == 2)
{
theLoremArray[i/3] = sb.toString();
// Log.d(TAG, "mLoremArray [" + i / 3 + "] = " + sb.toString());
sb.delete(0, sb.length());
}
}
ArrayList<String> words = new ArrayList<>();
for (int i = 0; i < theLoremArray.length; i++)
{
words.add( theLoremArray[i]);
}
return words;
}
class MyAdapter extends RecyclerView.Adapter<MyHolder>{
private List<String> data;
private String searchString = "";
MyAdapter(List<String> data){
this.data = data;
}
public void setFilter(List<String> listItems, String searchString){
// data = new ArrayList<>();
// data.addAll(listItems);
this.searchString = searchString;
notifyDataSetChanged();
}
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity8_grid_cell, null);
return new MyHolder(v);
}
@Override
public void onBindViewHolder(final MyHolder holder, int position)
{
holder.text.setText(data.get(position));
String todoHighlight = data.get(position);
// Set up the logic for the highlighted text
int todoStartPos = todoHighlight.indexOf(searchString);
int todoEndPos = todoStartPos + searchString.length();
Spannable spanString2 = Spannable.Factory.getInstance().newSpannable(holder.text.getText());
if(todoStartPos != -1 && searchString.length() > 0 && todoHighlight.contains(searchString)){
spanString2.setSpan(holder.getForegroundColorSpan(), todoStartPos, todoEndPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (searchString.length() == 0){
spanString2.removeSpan(holder.getForegroundColorSpan());
}
holder.text.setText(spanString2);
}
@Override
public int getItemCount()
{
return data.size();
}
}
class MyHolder extends RecyclerView.ViewHolder{
private ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.CYAN);
TextView text;
public MyHolder(View itemView){
super(itemView);
text = (TextView) itemView.findViewById(R.id.lorem_text);
}
public ForegroundColorSpan getForegroundColorSpan(){
return foregroundColorSpan;
}
}
}
activity8_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.samples.Activity8_RecyclerViewGrid">
<TextView
android:id="@+id/tvSearchText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
android:textColor="#ff0000" />
<Button android:id="@+id/btnFilter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="SET NEW FILTER"
android:layout_gravity="center_horizontal" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="80dp">
</android.support.v7.widget.RecyclerView>
</FrameLayout>
activity8_grid_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/lorem_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textAppearance="?android:attr/textAppearanceLarge" />
</FrameLayout>
关于安卓 Spannable : how to clear color?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45900950/
我想将 EditText 始终设置为 LTR,我该怎么做?android:textDirection 似乎确实是答案,我无法让项目使用该指令进行编译 最佳答案 为 editText 使用引力 andr
我希望我的应用在每次打开时都显示登录屏幕。使用 android:clearTaskOnLaunch="true" 一切正常。但是有一个错误,只有在手机关机并且应用程序首先使用小部件启动时才会发生。 I
实际上我的要求是我想将动态文件加载到像图像一样的网页中。视频,音频等,它来自 Assets 或应用程序自己的文件目录,这不是问题。 我尝试使用以下两种方式。 方式一 这是我的 html 文件在 ass
我正在触发一个 DatePickerDialog,在 api 22 (Android 5.1) 之前它一直在工作并显示良好,我在上面设置混合和最大日期(最小 = 当前日期,最大 = 从当前日期开始的
我有一个 ListView ,我在其中将标题 View 添加到该列表。一切都很好,但是当滚动列表 headerview 也随着列表移动时,所以我想避免 headerview 滚动,我的意思是当我列表到
虽然我在android上做过一些app,但我还是一头雾水。是否可以使用 SDK 4.0 中的功能,并在 android 2.1 或更低版本上运行该应用程序? 我尝试了你们提到的方法,但出现错误 - F
您好,我正在开发小型 android 应用程序,我想在其中显示带有一些元素的简单 gridview。它工作正常。唯一的问题是即使有空间,它也总是只显示两列。它平均将屏幕分成 2 列并仅显示两个元素。如
我正在使用 Android 2.3.3 API 构建一个应用程序。我需要识别方向的变化并执行一些操作。所以我在 Android Manifest 中添加了以下内容, android:configCha
我正在尝试在“点击”包含特定 MIME 类型的 nfc 标签时开始一项 Activity 。我制作了一个 mime 类型为“text/plain”的标签,并将其添加到 list 中:
我可以将一些数据保存到文件中 val byteArrayOutputStream = ByteArrayOutputStream() byteArrayOutputStream.wri
我正在尝试解析一个包含复杂阿拉伯字母的 XML 文件.. 当我在 android 2.3.7 上测试时,并不是所有的阿拉伯字母都被支持,仍然有一些复杂的显示为方 block .. 但是在 androi
我需要编写一个方法来确定设备是平板电脑还是手机。我不需要根据这个显示不同的用户界面。我只需要有关设备的信息,以便将来我可以将其发送到指标。 在互联网上,我找到了很多方法来确定设备是否是平板电脑。我已经
我正在玩文字转语音,让我的测试应用程序更有趣。它适用于模拟器,但不适用于我的手机,因为我的默认语言环境不是英语。 但是,文本是英文的,所以 tts 当然应该使用英文。据我所知,我可以实现一个自动安装,
我正在使用 MVVM 和整洁的架构编写应用程序。在其中一个屏幕上,我需要使用 pagination 实现 RecyclerView。我将使用库 Paging3。 Android 开发者推荐在存储库层使
这个问题在这里已经有了答案: I lost my .keystore file? (12 个回答) 4年前关闭。 当我以前的操作系统损坏并安装新的(7 月 3 日)时,以前的 android_key_
我正在使用 MVVM 和整洁的架构编写应用程序。在其中一个屏幕上,我需要使用 pagination 实现 RecyclerView。我将使用库 Paging3。 Android 开发者推荐在存储库层使
在我的 v27\style.xml 中,我有以下代码来设置白色导航栏: @color/colorPrimary @color/colorPrimaryDark @color/
我想通过发送电子邮件 startActivity(Intent.createChooser(new Intent(android.content.Intent.ACTION_SEND))) 我知道要将
我实现了一个自定义 ListView ,它看起来像 Twitter 时间线。 adapter = new MyClickableListAdapter(this, R.layout.timeline,
我有一个显示启动画面的自定义对话框; mSplashDialog = new Dialog(MyActivity.this,R.layout.splash); mSplashDialog.setCon
我是一名优秀的程序员,十分优秀!