【问题标题】:Change background color of selected item on a ListView更改 ListView 上所选项目的背景颜色
【发布时间】:2013-06-03 07:23:26
【问题描述】:

我想知道如何更改我的 listView 上所选项目的背景颜色。我只想更改用户单击的特定项目,这意味着如果用户单击另一个项目,它将是突出显示的项目。好吧,因为我希望它尽可能简单并使用默认的 android listview,所以我使用了以下代码:

record_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                try{
                    for (int ctr=0;ctr<=record_items.length;ctr++){
                        if(i==ctr){
                            record_list.getChildAt(ctr).setBackgroundColor(Color.CYAN);
                        }else{
                            record_list.getChildAt(ctr).setBackgroundColor(Color.WHITE);
                        }
                    }
                }
                catch (Exception e){
                    e.printStackTrace();
                }
                Log.v("Selected item",record_list.getItemAtPosition(i));
            }
        });

好的,这个正在工作,但问题是它很慢。现在我想知道是否有任何其他方法可以解决我的问题。

我尝试使用record_list.getSelectedView().setBackgroundColor(Color.CYAN);,但它给了我一个空指针异常。

我也尝试了 selector.xml,但它也没有成功。 此外,ListView 上还有一个属性,称为 listSelector。正如文档“Drawable used to指示列表中当前选定的项目”所述,它是一个drawable。我也相信这应该可以解决问题,是的,它可以在我的模拟器上解决问题,但不是在我的银河选项卡上。我也尝试了其他方法,但没有达到我想要的效果。

【问题讨论】:

  • 使用 xml 文件作为列表视图。
  • 这个选项你勾选了吗,list.setSelector(R.drawable.detail_hover);我的 deutil_hover 是 .png 可绘制对象。试试这个,希望对你有帮助。
  • 你在onitem点击中得到视图对象,所以改变那个视图的背景颜色并在下次点击时将它保存为prvsselected视图检查prvsselect视图是否为空,如果它不为空则改变它的颜色默认一个
  • 对于大于 1 个屏幕高度的列表,此方法将失败。
  • 2行有效解决方案:stackoverflow.com/questions/16976431/…

标签: android android-layout


【解决方案1】:

您可以跟踪当前选定元素的位置:

    OnItemClickListener listViewOnItemClick = new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapter, View arg1, int position, long id) {
                mSelectedItem = position;
                mAdapter.notifyDataSetChanged();
        }
    };

并覆盖适配器的 getView 方法:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final View view = View.inflate(context, R.layout.item_list, null);

        if (position == mSelectedItem) {
            // set your color
        }

        return view;
    }

对我来说,它成功了。

【讨论】:

  • 你应该只需要在 onItemClick 监听器中设置 view.setSelected(true):stackoverflow.com/questions/16189651/…
  • Esteam 的解决方案是正确的。仅使用 view.setSelected(true) 的问题是这些视图被回收。一旦您有一个足够大的列表可以滚动,这将不再有效。
  • 对我来说,我不得不使用id 而不是position,因为position 从 1 开始,而我的适配器中的项目从 0 开始。虽然我可能很少遇到这种情况,但是我想我会提到它以防有人被卡住。
  • @HuskyHuskie 不是因为你有一个标题视图吗?我总是使用position 并提取标题视图计数。
  • 这将在 Lollypop 中分解 - 如果您在项目上设置背景,您将不再看到那些花哨的点击动画。
【解决方案2】:

您可以使用选择器。更改颜色值并根据需要修改以下内容。

可绘制文件夹中的bkg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" 
    android:drawable="@drawable/pressed" />
<item  android:state_focused="false" 
    android:drawable="@drawable/normal" />
</selector>

drawable 文件夹中的pressed.xml

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
<solid android:color="#FF1A47"/>  // color   
<stroke android:width="3dp"
        android:color="#0FECFF"/> // border
<padding android:left="5dp"
         android:top="5dp"
         android:right="5dp"
         android:bottom="5dp"/> 
<corners android:bottomRightRadius="7dp" // for rounded corners
         android:bottomLeftRadius="7dp" 
         android:topLeftRadius="7dp"
         android:topRightRadius="7dp"/> 
</shape>

drawable 文件夹中的 normal.xml

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
<solid android:color="#FFFFFF"/>    
<stroke android:width="3dp"
        android:color="#0FECFF" />

<padding android:left="5dp"
         android:top="5dp"
         android:right="5dp"
         android:bottom="5dp"/> 
<corners android:bottomRightRadius="7dp"
         android:bottomLeftRadius="7dp" 
         android:topLeftRadius="7dp"
         android:topRightRadius="7dp"/> 
</shape>

将背景drawable设置为listview自定义布局,为每一行充气

我建议使用带有自定义适配器的自定义列表视图。

  android:background="@drawable/bkg"     

如果您没有使用自定义适配器,您可以将 listselector 设置为 listview,如下所示

   android:listSelector="@drawable/bkg" 

【讨论】:

  • 我试过这段代码,但是当我点击列表项时,它的颜色只会改变几秒钟,如果我想将项目显示为选中。
  • @rb16 这就是选择器的用途。如果不是,您正在寻找不同的解决方案,而不是这个
  • 目前,当我点击一个列表项时,它的颜色会改变,而它在释放它的颜色更改为默认颜色后按下它。但我的要求是我想将点击的项目显示为选中,直到我不点击在其他列表项上
  • 为了选择项目,将state_selected="true" 的条目添加到选择器xml。
  • 仅仅改变背景颜色需要另外 3 个 xml 文件。天哪……
【解决方案3】:

定义变量

private ListView mListView;

初始化变量

mListView = (ListView)findViewById(R.id.list_view);

列表视图的 OnItemClickListener

   mListView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adpterView, View view, int position,
                long id) {
            for (int i = 0; i < mListView.getChildCount(); i++) {
                if(position == i ){
                    mListView.getChildAt(i).setBackgroundColor(Color.BLUE);     
                }else{
                    mListView.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
                }
            }
        }
    });

构建并运行项目 - 完成

【讨论】:

  • 嗨,您的答案与我尝试实施的答案几乎相同,但没有按我想要的方式工作。近两年前,这个问题也得到了回答和接受。 :)
  • @KaHeL,感谢分享关注,我已经尝试了上述和其他解决方案,但我无法获得正确的结果,所以我用自己的解决方案尝试了它,幸运的是它对我有用。谢谢
  • 这个有效!该解决方案对我有用,而其他解决方案则没有。我在“selectItem(position);”行之后将这个“for”语句添加到我的导航抽屉中。现在它就像一个魅力。点赞!我需要解释为什么这个工作:otherS 留下了选中的选项,所以,在选择另一个之后,有两个选项被选中,这个解决方案改变了所有选项的颜色,只有一个保持所需的颜色。
  • @JoseManuelAbarcaRodríguez,很高兴为您提供帮助并感谢您的赞赏。 :)
  • 小心,如果列表超过一个屏幕高度,它会被空指针压碎。另外,如果你有一个包含数千个项目的列表,当你只看到几个时它会一个接一个。
【解决方案4】:

如果您希望在单击后使项目保持突出显示,则需要手动将其设置为在 onItemClick 侦听器中被选中

Android ListView selected item stay highlighted:

myList.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {   
        view.setSelected(true); // <== Will cause the highlight to remain
        //... do more stuff                          
    }});

这假设您的选择器中有一个 state_selected 项:

<?xml version="1.0" encoding="utf-8"?>
  <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  <item android:state_enabled="true" android:state_pressed="true" android:drawable="@color/red" />
  <item android:state_enabled="true" android:state_focused="true" android:drawable="@color/red" />
  <item android:state_enabled="true" android:state_selected="true" android:drawable="@color/red" />
  <item android:drawable="@color/white" />
</selector>

【讨论】:

  • view.setSelected(true); 使我的项目始终被选中。如何让它不被选中?
  • @Sonhja 您应该每次默认取消选中每个项目并检查 getView 如果等于所选位置然后选择 true 否则为 false
【解决方案5】:

方法一:

在您的 xml 布局活动/片段中更新 ListView:

<ListView
   ...
   android:choiceMode="singleChoice"
   android:listSelector="@android:color/darker_gray"
/>

就是这样,你完成了!

如果您想以编程方式处理此问题,请使用方法 2...

方法二:

如果您使用 ListFragment,您可以覆盖 onListItemClick(),使用视图设置颜色。保存当前选择的视图以重置最后选择的颜色。

请注意,这仅适用于适合一个屏幕的列表视图,因为视图会被回收。

public class MyListFragment extends ListFragment {
    View previousSelectedItem;
...
    @Override
    public void onListItemClick(ListView parent, View v, int position, long id) {
        super.onListItemClick(parent, v, position, id);
        if (previousSelectedItem!=null) {
            previousSelectedItem.setBackgroundColor(Color.WHITE);
        }
        previousSelectedItem=v;
        v.setBackgroundColor(Color.BLUE);
    }
}

【讨论】:

    【解决方案6】:

    对于那些想知道究竟需要做什么来保持选中行的人,即使您向上向下滚动也是如此。就是 state_activated 其余的由内部功能处理,您不必担心切换,并且可以选择多个项目。我不需要使用 notifyDataSetChanged() 或 setSelected(true) 方法。

    将此行添加到您的选择器文件中,对我来说 drawable\row_background.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light"/>
    
        <item android:state_enabled="true" android:state_pressed="true" android:drawable="@android:color/holo_blue_light" />
        <item android:state_enabled="true" android:state_focused="true" android:drawable="@android:color/holo_blue_bright" />
        <item android:state_enabled="true" android:state_selected="true" android:drawable="@android:color/holo_blue_light" />
        <item android:state_activated="true" android:drawable="@android:color/holo_blue_light" />
    
        <item android:drawable="@android:color/transparent"/>
    </selector>
    

    然后在 layout\custom_row.xml 中

    <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="10dip"
            android:background="@drawable/row_background"
            android:orientation="vertical">
      <TextView
            android:id="@+id/line1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    

    有关更多信息,我将它与 ListView 适配器一起使用,使用 myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 和 myList.setMultiChoiceModeListener(new MultiChoiceModeListener()...

    来自这个例子:http://www.androidbegin.com/tutorial/android-delete-multiple-selected-items-listview-tutorial/

    此外,您(应该)使用此结构进行列表适配器耦合:List myList = new ArrayList();

    代替:ArrayList myList = new ArrayList();

    解释:Type List vs type ArrayList in Java

    【讨论】:

    • 感谢您的回答。
    • 嗨,Emil,您的解决方案是否可以通过编程方式取消选择该项目?
    • 嗨@Sam,我的解决方案基于我链接的示例。这是一个非常好的 ListView 教程,在此之后,您将大致了解 Lists 的工作原理以及代码如何与 XML 文件交互。你必须知道那里提供的所有信息,跳过这个太基础了,那个教程是直截了当的。我浏览了其他几个,但他们的介绍太混乱或误导了,所以中途放弃了。一旦“自动”工作,试试这个程序化方法:stackoverflow.com/questions/10788688/…
    【解决方案7】:

    首先,您可以在您的可绘制文件夹drawable/list_item_selector.xml 中创建如下所示的选择器 xml 文件

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:state_activated="true">
          <shape android:shape="rectangle">
            <solid android:color="#333333" />
            <padding android:left="5dp" android:right="5dp" />
          </shape></item>
        <item><shape android:shape="rectangle">
                <solid android:color="#222222" />
            </shape></item>
    
    </selector>
    

    然后在您的列表视图中指定背景为

    android:background="@drawable/list_item_selector"
    

    【讨论】:

    • 这个很有趣。我会试试这个,稍后再给你反馈。 :)
    • 嗨,使用这种方法,是否可以通过编程方式取消选择该项目?谢谢...
    【解决方案8】:

    我发现的最简单的方法:

    在您的活动 XML 中添加以下行:

    <ListView 
    ... 
    android:choiceMode="singleChoice"
    android:listSelector="#666666"
    />
    

    或以编程方式设置这些属性:

    listView.setSelector(Drawable selector)
    listView.setSelector(int resourceId)
    

    我的具体例子:

       <ListView
                android:choiceMode="singleChoice"
                android:listSelector="#666666"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/listView"/>
    

    感谢 AJG: https://stackoverflow.com/a/25131125/1687010

    【讨论】:

      【解决方案9】:

      我也在做类似的事情:突出显示所选列表项的背景(将其更改为红色)并将项目中的文本颜色设置为白色。

      我可以想出一个“简单但效率不高”的方法: 在自定义适配器中维护选定项的位置,并在 ListView 的OnItemClickListener 实现中更改它:

      // The OnItemClickListener implementation
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          mListViewAdapter.setSelectedItem(position);
      }
      
      // The custom Adapter
      private int mSelectedPosition = -1;
      public void setSelectedItem (int itemPosition) {
          mSelectedPosition = itemPosition;
          notifyDataSetChanged();
      }
      

      然后在getView()方法中更新选中项的背景和文字颜色。

      // The custom Adapter
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          ...
          if (position == mSelectedPosition) {
              // customize the selected item's background and sub views
              convertView.setBackgroundColor(YOUR_HIGHLIGHT_COLOR);
              textView.setTextColor(TEXT_COLOR);
          } else {
              ...
          }
      }
      

      搜索了一会,发现很多人提到要设置android:listSelector="YOUR_SELECTOR"。经过一段时间的尝试,我发现最简单的方法是突出显示选定的 ListView 项目的背景,只需将两行设置为 ListView 的布局资源:

      android:choiceMode="singleChoice"
      android:listSelector="YOUR_COLOR"
      

      还有其他方法可以使它工作,例如自定义activatedBackgroundIndicator 主题。但我认为这将是一个更通用的解决方案,因为它会影响整个主题。

      【讨论】:

        【解决方案10】:
        View updateview;// above oncreate method
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        
        
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 if (updateview != null) 
                    updateview.setBackgroundColor(Color.TRANSPARENT);
                 updateview = view;   
        
                 view.setBackgroundColor(Color.CYAN);
             }
        });
        

        【讨论】:

        • 这是我能找到的最简单的方法。只要您选择列表中的另一个元素,只有一个项目将保持突出显示。上一个将被自动取消选择
        • 与已经接受的答案相比,您的答案提供了什么?
        【解决方案11】:

        使用下面的 xml 作为 listitem 背景,它将解决所有问题。 尽管您向下滚动,所选内容仍会突出显示。

        <?xml version="1.0" encoding="utf-8"?>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@android:color/holo_orange_dark" android:state_pressed="true"/>
        <item android:drawable="@android:color/holo_green_light" android:state_selected="true"/>
        <item android:drawable="@android:color/holo_green_light" android:state_activated="true"/>
        

        谢谢, 纳根德拉

        【讨论】:

        • 嗨,Nagendra,您的解决方案是否可以通过编程方式取消选择该项目?
        【解决方案12】:

        我知道这是一个老问题,但我为这个需求提供了一个简单的解决方案(没有循环!):

        //On your adapter create a variable:
        private View lastSelectedItem;
        
        //Define the folowing method:
        private void toggleBackgroundItem(View view) {
            if (lastSelectedItem != null) {
                lastSelectedItem.setBackgroundColor(Color.TRANSPARENT);
            }
            view.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
            lastSelectedItem = view;
        
        }
        //finally invoque the method onItemClick
        lvSac.setOnItemClickListener(new AdapterView.OnItemClickListener()
        
        {
            @Override
            public void onItemClick (AdapterView < ? > adapterView, View view,int i, long l){
        
            toggleBackgroundItem(view);
        }
        }
        

        【讨论】:

          【解决方案13】:

          在 ListView 集中:

          android:choiceMode="singleChoice"
          

          为背景创建一个选择器(drawable/selector_gray.xml):

          <?xml version="1.0" encoding="utf-8"?>
          <selector xmlns:android="http://schemas.android.com/apk/res/android">
              <item android:drawable="@color/gray" android:state_checked="true" />
              <item android:drawable="@color/white" />
          </selector>
          

          为列表添加一个项目:

          <?xml version="1.0" encoding="utf-8"?>
          <TextView
              xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:padding="5dp"
              android:background="@drawable/selector_gray"
              android:textColor="@color/colorPrimary"
              tools:text="Your text" />
          

          您可以在 ViewHolder 中为该项目充气。

          【讨论】:

          • 我将“android:state_checked”更改为“android:state_selected”,当我在列表视图的 onItemClickedListener 中调用 view.setSelected(true) 时,它可以工作。
          • @civic.LiLister,谢谢,这是一个好点。我认为,它可以取决于列表项。但请同意,您的变体更有帮助,也更常用。
          【解决方案14】:

          假设您希望每次点击一个项目。然后这段代码运行良好。让我们将列表视图名称作为 stlist

          stList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                  @Override
                  // here i overide the onitemclick method in onitemclick listener
                      public void onItemClick(AdapterView<?> parent, View view,
                                          int position, long id) {
          
                      //color change
                      //selected item colored
          
                      for(int i=0; i<stList.getAdapter().getCount();i++)
                      {
                          stList.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
                      }
          
                      parent.getChildAt(position).setBackgroundColor(Color.GRAY);
          
              });
          

          【讨论】:

          • 小心,如果列表超过一个屏幕高度,它会被空指针压碎。另外,如果你有一个包含数千个项目的列表,当你只看到几个时它会一个接一个。
          【解决方案15】:

          这是一个简单的方法,即使列表也很长,也可以处理选择:

          public View getView(final int position, View convertView, ViewGroup parent) {
              // TODO Auto-generated method stub
              Holder holder=new Holder();
              View rowView;
              rowView = inflater.inflate(R.layout.list_item, null);
              //Handle your items.
              //StringHolder.mSelectedItem is a public static variable.
              if(getItemId(position)==StringHolder.mSelectedItem){
                  rowView.setBackgroundColor(Color.LTGRAY);
          
              }else{
                  rowView.setBackgroundColor(Color.TRANSPARENT);
              }
              return rowView;
          }
          

          然后在你的 onclicklistener 中:

          list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                  @Override
                  public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                      StringHolder.mSelectedItem = catagoryAdapter.getItemId(i-1);
                      catagoryAdapter.notifyDataSetChanged();
          .....
          

          【讨论】:

          • 什么是StringHolder
          【解决方案16】:

          nameofList.getChildAt(position).setBackgroundColor(RED);

          为我工作

          【讨论】:

            【解决方案17】:

            这很简单。在“OnItemClick”的构造函数中使用参数“view”,它是代表listView或GridView的项目视图的第二个参数,它成为adapterView自己制作的新项目的视图。因此,要仅为 SELECTED ITEM 本身设置新颜色,请执行以下操作:

            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l){ //view is instead of the view like textView , ImageView, or whatever view.setBackgroundColor(Color.green); }

            如果您执行任何不同的代码来设置新颜色,您将面临尴尬的行为,例如绿色将应用于未点击的项目。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-10
              • 1970-01-01
              • 2021-05-25
              • 1970-01-01
              • 2011-01-14
              相关资源
              最近更新 更多