Android Spannable:如何清除颜色?

2024-01-05

我在 RecyclerView CardViews 的 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);
    }
}

视图持有者:

class MyViewHolder extends RecyclerView.ViewHolder{
    private ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);

    public MyViewHolder(View itemView){
        super(itemView);
    }

    public ForegroundColorSpan getForegroundColorSpan(){
        return foregroundColorSpan;
    }
}

EDIT远程调试很困难,所以让我们以另一种方式进行,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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Spannable:如何清除颜色? 的相关文章

  • Xamarin Android Webview Javascript

    我正在尝试通过 Xamarin for Android 创建一个移动应用程序 它有一个显示网站的 WebView 问题是正常按钮会触发 但 javascript 事件不会触发 我已经启用了 Javascript 但没有运气 如何在 Andr
  • 从响应中获取标头(Retrofit / OkHttp 客户端)

    我正在使用 Retrofit 与 OkHttp 客户端和 Jackson 进行 Json 序列化 并希望获取响应的标头 我知道我可以扩展 OkClient 并拦截它 但这发生在反序列化过程开始之前 我基本上需要的是获取标头以及反序列化的 J
  • 如何正确释放Android MediaPlayer

    我正在尝试向我的 Android 应用程序添加一个按钮 当点击该按钮时它会播放 MP3 我已经让它工作了 但没有办法释放 mediaPlayer 对象 因此即使在我离开活动后它仍然会继续播放 如果我在react 方法之外初始化MediaPl
  • fetchUuidsWithSdp 的奇怪 UUID 逆转

    我有一个在树莓派上运行的 python 蓝牙服务器 使用 PyBluez 我在服务器中使用的uuid是 8f86d132 4ab8 4c15 b8df 0b70cf10ea56 我正在打电话device fetchUuidsWithSdp
  • 如何使用 Google Maps for Android V2 处理地图移动结束?

    我想在地图中心更改后立即对地址进行地理编码 如何使用新的 Android 版 Google 地图 V2 处理地图移动 我说的是用户用手指拖动地图的情况 查看新的地图 API Override public void onMapReady G
  • Android 初学者:Android gridview 中的触摸事件

    我正在使用以下代码来使用 gridview 执行操作 稍作修改http developer android com resources tutorials views hello gridview html http developer a
  • Dialog.setTitle 不显示标题

    我正在尝试向我的对话框添加自定义标题 但是每当我运行我的应用程序时 它都不会显示标题 我创建对话框的代码是 final Dialog passwordDialog new Dialog this passwordDialog setCont
  • 当它的父级是 ConstraintLayout 时设计 CardView 吗?

    我在编辑包含Relativelayout的Cardview内的RelativeLayout时搞砸了 ConstraintLayout会将相对布局的wrap content更改为0并添加工具 layout editor absoluteX 1
  • Android Eclipse 上的 Web 服务

    我是 android eclipse java 的新手 事实上这个论坛也是如此 有人遇到过这种情况吗 从用户那里获取输入并通过使用 android eclipse 中的 Web 服务来显示适当的结果 有可用的示例吗 非常感谢 我正在发布教程
  • Mipmap 与可绘制文件夹[重复]

    这个问题在这里已经有答案了 我正在使用 Android Studio 1 1 Preview 1 我注意到 当我创建一个新项目时 我得到以下层次结构 不同 DPI 的 Mipmap 文件夹 不再有不同 DPI 的可绘制文件夹 我应该将所有资
  • Android 中如何通过彩信发送图片?

    我正在开发多媒体应用程序 我正在通过相机捕获一张图像 并希望将该图像和文本发送到其他号码 但我不知道如何通过彩信发送图像 MMS 只是一个 http post 请求 您应该使用执行请求额外的网络功能 final ConnectivityMa
  • WorkManager 或 AlarmManager 用于日常请求然后通知工作?

    这是用例 用户设置具有特定时间的每日通知 在指定时间 发出网络请求以获取一些数据 然后使用检索到的数据显示通知 我不确定是否应该使用 AlarmManager 还是 WorkManager 来实现这个用例 据我了解 AlarmManager
  • 我应该释放或重置 MediaPlayer 吗?

    我有自己的自定义适配器类 称为 WordAdapter 并且我正在使用媒体播放器 名为pronounce WordAdapter 类中的全局变量 我有不同的活动 其中每个列表项都有线性布局 名为linearLayout 我正在设置onCli
  • OnLongClickListener 不工作

    我有一个ImageView 我需要使用onLongClickListener对于图像视图 当我使用这段代码时 什么也没有发生 Code gallery Gallery findViewById R id gall1 gallery setA
  • 您使用什么物理 Android 设备进行测试?

    有什么好的推荐用于测试目的的物理 Android 设备吗 我正在苹果阵营寻找像 iPod touch 这样的设备 可以帮助 iOS 开发人员测试他们的东西 我知道有 Nexus One 但那东西相当昂贵 而且我并不真正关心手机的东西 而是可
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 通过系统应用程序以编程方式静默安装 apk(无需 root)

    我有带有 android sharedUserId android uid system UID 1000 的系统级应用程序 设备未root INSTALL PACKAGES 权限包含在清单中 我可以静默安装下载的 apk 吗 我已经发现这
  • 如何使用 AccessibilityService 在 Android 中模拟按键

    我正在编写一个辅助服务 我一直在尝试在应用程序上进行一些自动搜索 我使用accessibilityservice action paste来填充EditText 然后我需要模拟软键盘上的按键 但我不知道如何做 你们能帮我一下吗 你可以尝试A
  • 发布的 Android apk 出现错误“包文件未正确签名”

    我最近将我的应用程序上传到 Android 市场 但是由于错误 下载时它拒绝运行 包文件未正确签名 我首先使用 eclipse 发布了数据包 右键单击导出 创建密钥库然后发布 但它拒绝工作 然后我下载了 keytool 和 jarsigne

随机推荐

  • Java 递归暴力迷宫求解器

    在尝试编写一个强力解决迷宫的 C 程序时 我首先编写了这个 java 程序来测试一个想法 我对 C 很陌生 打算在 Java 中正确使用它后将其转换 因此 我尝试远离数组列表 花哨的库等 以便更容易转换为 C 该程序需要生成最短步骤的单宽度
  • PHP 和 Wordpress 中的调试

    ini set log errors On and define WP DEBUG true 我正在尝试创建一个错误日志文件 但我对这两个文件感到困惑 会出现什么样的错误log errors and WP DEBUG The define
  • 使用 C# 从 SQL Server 数据生成 XML

    我在 SQL Server 中有一个生成 XML 输出的查询 我想使用 C 产生相同的结果 是否可以 查询是 select T1 1 HomeID as HomeID select T1 2 DayID as ID select T2 Rn
  • com.sun.xml.internal.ws.client 不存在

    我试图捕获 ClientTransportException 但我的程序在编译阶段失败 出现以下异常 ERROR workspace rates java service bundle1 src main java com connecto
  • 有没有办法知道 NSUserNotificationCenter 中有多少个 NSUserNotification?

    Is there any non private way of knowing how many notifications there are in the Notification Center NSUserNotificationCe
  • 为什么 PDO fetchColumn() 在这里不起作用

    我正在尝试计算查询返回的行数 我正在这样做 what Norman stmt conn gt prepare select names as names from names where names what stmt gt bindPar
  • 如何为文本框添加效果到样式

    我试图向样式添加效果以便重用它 但由于某种原因它不起作用
  • Spring REST 返回 PDF - 响应状态 406(不可接受)

    我读了很多关于此类问题的问题 但他们都建议使用正确的杰克逊版本 这是我目前的情况 休息 API RequestMapping value get pdf id headers Accept method RequestMethod GET
  • Swift Combine:将发布者转变为只读 CurrentValueSubject

    有时我的视图模型使用 Published财产或PassthroughSubject 但我不希望它对外界可写 很简单 把它变成公共的AnyPublisher并将可写的保留为私有 如下所示 class ViewModel Published p
  • Google API Oauth .net core 3.1

    我有一个 net core 3 1 MVC Web 应用程序 我正在尝试开始使用一些谷歌 API 我发现谷歌文 档非常混乱 在官方文档中 我发现 MVC 库不支持 net core 有人可以为我指明正确的方向 我应该如何开始在 MVC ne
  • 使用 ArcGIS JS API 的 dojo 解析器和 TypeError

    我收到此错误 类型错误 未定义 不是函数 评估 parser parse 这是我的代码
  • 未启用时更改按钮背景

    我需要改变我的Button仅当未启用背景 例如 SolidColorBrush 时 IsEnabled false 我能怎么做 我要修改按钮吗Style使用 XAML 或者我可以通过编程方式完成这项工作吗 在未启用背景时仅更改背景的正确 X
  • 使用 jQuery 按顺序添加和删除类

    我想说的是 如果我的 div 没有活动类 请添加它 如果该类确实处于活动状态 请将其删除 我有以下内容 只有我的代码添加了该类 然后继续查询并在最后删除它 最好的解决方案是什么 2个单独的单击功能 work showcase click f
  • Woocommerce 根据所选的运输类别在结账时更改运输方式标题

    我想根据产品的运输类别更改商店结帐中显示的运输方式标题 e g 运输方式标题目前为统一费率 我有 2 个产品 如果购买产品 A 我需要它有 易碎品运输 如果购买产品 B 我需要它具有 标准运输 遗憾的是 我必须使用类来进行运输 因此其他方法
  • Angular 2 服务的异步初始化

    我有一个 Angular 2 服务 需要在初始化时执行异步工作 并且在初始化完成之前不应该使用 Injectable export class Api private user private storage constructor pri
  • Numpy 数组广播规则

    我在理解 Numpy 中数组广播的规则时遇到一些困难 显然 如果对两个具有相同维度和形状的数组执行逐元素乘法 一切都很好 另外 如果将多维数组乘以标量 它就会起作用 这我明白了 但是如果你有两个 N 维数组不同的形状 我不清楚广播规则到底是
  • 检测到 jQuery.ajax 调用因页面正在重新加载而失败?

    我进行了大量的 ajax 调用 并以抛出消息的方式处理来自它们的错误 我发现如果在页面重新加载时正在进行 ajax 调用 例如单击刷新 或导航到另一个 URL 然后我正在进行的 ajax 调用会触发它们的错误回调 如何区分真正的错误和因页面
  • 向 qmake 添加一个带有值的定义?

    如何使用 qmake 添加带有值的定义 例如 这在我的 pro 文件中不起作用 如我所料 DEFINES WINVER 0x0500 nor DEFINES WINVER 0x0500 如何在开始编译之前将 WINVER 定义为 0x050
  • 如何隐藏DataGridView的网格线? Winforms C#

    如何隐藏DataGridView的网格线 我在互联网上搜索过但没有找到解决方案 请帮忙 谢谢 你可以试试 MyGrid CellBorderStyle DataGridViewCellBorderStyle None
  • Android Spannable:如何清除颜色?

    我在 RecyclerView CardViews 的 SearchView 上设置了 Spannable 如果在 CardView 上找到用户输入的文本 则该文本将以红色突出显示 当 SearchView 行被清除时 我希望 CardVi