【问题标题】:How to highlight row in ListView in Android?如何在 Android 的 ListView 中突出显示行?
【发布时间】:2011-05-08 06:00:16
【问题描述】:

我需要在ListView 中突出显示选中的一行(向用户展示他选择的内容),因此,这不是将要选择的那个,而是他之前选择的那个。

我已经有了位置:

ListView.setSelection(position);

现在我想要的是选择这个特定的行并突出显示它。

包含ListView的活动中onCreate()的代码:

public class CountryView extends Activity
{
    protected static final String LOG_TAG = null;
    /** Called when the activity is first created. */
    String[] lv_arr = {};

    ListAdapter adapter;
    TextView t;
    private ListView lvUsers;
    private ArrayList<Coun> mListUsers;
    String responce=null;
    public int d;
    int selectedListItem = -1;


    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.country);

        Intent data =getIntent();

        mListUsers = getCoun();
        lvUsers = (ListView) findViewById(R.id.counlistView);


        lvUsers.setAdapter(new ListAdapter(this, R.id.counlistView, mListUsers)); 


        selectedListItem=data.getExtras().getInt("PositionInList");

       lvUsers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);



        lvUsers.setOnItemClickListener(new OnItemClickListener()
        {

            int positionItem;

            public void onItemClick(AdapterView<?> parent, View view,int position, long id)
            {
                Intent pongIntent = new Intent(getApplicationContext(),Trav.class);

                int counId=mListUsers.get(position).id;

                pongIntent.putExtra("response",mListUsers.get(position).p);
                pongIntent.putExtra("responseCounID",counId);

                //Put the position of the choose list inside extra
                positionItem=position;
                pongIntent.putExtra("PositionInListSet",positionItem);

                setResult(Activity.RESULT_OK,pongIntent);

                Log.i("CounID *******************************"," "+counId);
                finish();
            }
         });
    }
}

【问题讨论】:

    标签: android android-listview


    【解决方案1】:

    由于默认ListViews 设置为NONE 的选择模式,在触摸模式下setSelection 方法不会有视觉效果。

    为了保持之前的选择/直观地显示一个明确的选择,首先你必须适当地设置你的列表视图的选择模式:

    listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    

    阅读这些方法的 API 文档很有用:

    • setSelection
    void android.widget.AdapterView.setSelection(int position)
    

    设置当前选中的项目。到 支持可访问性子类 重写此方法必须调用 首先覆盖超级方法。

    参数
    position要选择的数据项的索引(从0开始)。

    • setChoiceMode
    void android.widget.ListView.setChoiceMode(int choiceMode)
    

    定义选择行为 列表。默认情况下,列表没有 任何选择行为 (CHOICE_MODE_NONE)。通过设置 选择模式为CHOICE_MODE_SINGLE, 列表最多允许一个项目在一个 选择的状态。通过设置 选择模式为CHOICE_MODE_MULTIPLE, 该列表允许任意数量的项目 被选中。

    参数
    choiceMode CHOICE_MODE_NONE之一, CHOICE_MODE_SINGLE,或 CHOICE_MODE_MULTIPLE

    如果这还不够(假设您希望始终在当前选择旁边以不同的方式显示最后一个选择),您应该将您最后选择的项目(填充ListAdapter 的数据)存储为lastSelectedItem,并在适配器的 getView 方法中为渲染器分配不同的背景资源,如果它等于 lastSelectedItem

    如果您的最后一个选择不会在选择更改时刷新,您应该在您的适配器实例上显式调用notifyDataSetChanged 方法。

    更新
    由于您包含ListView 的活动是等待此结果的活动的子项(基于setResult(Activity.RESULT_OK,pongIntent); 部分),因此最初的想法是正确的,最后一个位置应该在启动活动时通过意图传递:

    selectedListItem = getIntent().getIntExtra("PositionInList", -1);
    lvUsers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    lvUsers.setSelection(selectedListItem);
    

    ListView.CHOICE_MODE_SINGLE 解决方案如果您保持在同一个活动中将起作用,但您在每次 itemClick(选择更改)上完成它,这就是为什么应该将额外数据传递给起始 Intent

    您还可以从您的适配器设置先前选择的项目的背景 - 如上所述 - 覆盖其 getView 方法:

    lvUsers.setAdapter(new ArrayAdapter(this, R.id.counlistView, groups)
    {
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            final View renderer = super.getView(position, convertView, parent);
            if (position == selectedListItem)
            {
                //TODO: set the proper selection color here:
                renderer.setBackgroundResource(android.R.color.darker_gray);
            }
            return renderer;
        }
    });
    

    【讨论】:

    • 没关系,这将是相同的颜色,因为当用户选择了旧的选择需要消失时,我去的只是在他选择旧的选择之前会突出显示
    • 如果您想在选择新项目之前保留选择,将列表视图的选择模式设置为CHOICE_MODE_SINGLE 就足够了。
    • 在您的活动的onCreate 方法中,您应该设置listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);,您甚至不需要显式设置选择 (listview.setSelection(position);)。如果它不起作用,请分享您的代码,以帮助我们检测问题的根源。谢谢。
    • 感谢您的代码,它让事情变得更清晰:重要的是,您在选择更改时完成此活动。如果先前选择的项目的位置在意图之间正确传递,我的答案的更新部分应该适合你。
    • 您好!你知道如何使用stateListDrawable 作为背景获得相同的结果吗?看来如果我使用view.setSelected(true) - 它没有效果
    【解决方案2】:

    只是:

    1. 在列表视图中设置正确的选择模式。 setChoiceMode
    2. 设置背景以支持您的项目布局中的选择状态,例如:

      android:background="?android:attr/activatedBackgroundIndicator"
      

    仅供参考:

    【讨论】:

    • 非常感谢。 :-) 我错过了 #2 并且很长时间都在搞乱代码。
    • xml设置,可以设置android:choiceMode="singleChoice",developer.android.com/reference/android/widget/…
    • 在尝试了很多解决方案之后。我可以说这是其中最好的。
    • 也为我工作。
    【解决方案3】:

    在您的布局文件中实现这一点要容易得多,其余的交给 Android 处理...

    1) 确保在 ListView 布局 上设置了android:choiceMode=""singleChoicemultipleChoice 等)。默认设置为none

    <ListView
        android:id="@+id/invite_friends_fragment_contacts_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:choiceMode="multipleChoice"/> <!-- THIS LINE -->
    

    2) 创建一个状态选择器 XML 文件并将其保存在您的 drawables 文件夹中。在本例中,我们将其命名为 state_selector.xml

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

    3)在您的列表项布局中,添加 state_selector.xml 文件作为背景:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/state_selector">  <!-- THIS LINE -->
    
        <!-- ALL OF YOUR ELEMENTS WILL GO HERE (TextViews, ImageViews, etc) -->
    
    </RelativeLayout>
    

    如果您使用multipleChoice,您可以覆盖onItemClick()set/unset selected items accordingly。 Android 将更改您在 state_selector.xml 文件中指定的背景颜色。

    【讨论】:

    • 对我来说,魔线是android:state_activated="true",而我不需要android:state_selected。谢谢!
    • 谢谢,这样我可以设置自定义颜色,尽管 "?android:attr/activatedBackgroundIndicator" 有效。
    【解决方案4】:

    我很难找到一个简单的解决方案,因为太多教程和答案都包含有关通过单选按钮进行单选的信息(这在很大程度上依赖于 RadioGroup)。

    我的问题是我可以将项目设置为“突出显示”状态,但在选择下一个项目时无法重置列表。这是我想出的:

    listView.setOnItemClickListener(new ItemHighlighterListener ());
    

    有了这个类:

    private class ItemHighlighterListener implements OnItemClickListener{
    
        private View lastSelectedView = null;
    
        public void clearSelection()
        {
            if(lastSelectedView != null) lastSelectedView.setBackgroundColor(android.R.color.transparent);
        }
    
        @Override
        public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) {
            clearSelection();
            lastSelectedView = view;
            view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.shape_selected_menu_item));
        }
    }
    

    【讨论】:

      【解决方案5】:

      我通过以下方式解决了这个问题: 1.设置一个lastClickId,当点击listView中的item时,更新lastClickId为位置值,然后更新view的背景。 之后,当我们单击一个项目时,该项目将被突出显示,但是当我们滚动 listView(使我们选择的项目离开屏幕)并向后滚动时,突出显示消失了,因为 getView() 方法重新运行你的适配器,所以,我们必须做下一件事。 2. 在你的适配器中,通过getView()方法改变背景,代码如下:

      private static int lastClickId = -1;
      private OnItemClickListener listener = new OnItemClickListener() {
      
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position,
                  long id) {
              if ((lastClickId != -1) && (lastClickId != position)) {
                  parent.getChildAt(lastClickId).setBackgroundResource(
                          R.color.grey);
                  view.setBackgroundResource(R.color.blue);
              }
              if (lastClickId == -1) {
                  view.setBackgroundResource(R.color.blue);
              }
              lastClickId = position;
      
          }
      
      };
      
      public static int getCurrentSelectedItemId() {
          return lastClickId;
      }
      

      适配器:

      public View getView(int position, View convertView, ViewGroup parent) {
          // TODO Auto-generated method stub
      
          View view = mInflater.inflate(R.layout.tweet_list_layout, null);
          // set selected item's background to blue
          if (position == MainUserFeedFragment.getCurrentSelectedItemId()) {
              view.setBackgroundResource(R.color.blue);
              }
          }
      

      【讨论】:

      • 好的。这看起来很清楚,但请注意视图可能会在列表视图中重复使用,并且没有机会重置颜色。因此,我建议在getView()方法中,我们应该添加一个else case来重置颜色。说else view.setBackgroundResource(R.color.grey);
      【解决方案6】:

      为什么不将选择存储在一个数组中,然后将该数组传递给 ListView 数组适配器的构造函数,类似于 myArrayAdapter(context,layoutID,dataArray,selectionArray)

      然后在您的阵列适配器的getView 方法中,进行检查。例如在伪代码中

      if row was previously selected
          change background color
      

      【讨论】:

        【解决方案7】:

        您可以使用过渡。遵循我的代码,因为我已经通过选择实现了对特定列表视图项的突出显示 假设您要突出显示第一项 5 秒钟。

         if(position == 0){
                            viewHolderThubnail.relImage.setBackgroundResource(R.drawable.translate);
                            TransitionDrawable transition = (TransitionDrawable) viewHolderThubnail.relImage.getBackground();
                            transition.startTransition(1000);
        
                        }else{
        
                            viewHolderThubnail.relImage.setBackgroundResource(R.color.white);
                        }
        

        translate.xml

        <?xml version="1.0" encoding="UTF-8"?>
           <transition xmlns:android="http://schemas.android.com/apk/res/android">
                  <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
                  <item android:drawable="@drawable/new_state" />
                  <item android:drawable="@drawable/original_state" />
           </transition>
        

        new_state.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <shape   xmlns:android="http://schemas.android.com/apk/res/android"
                    android:shape="rectangle">
            <solid android:color="#92BCE7"/>
        </shape>
        

        original_state.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <shape   xmlns:android="http://schemas.android.com/apk/res/android"
                    android:shape="rectangle">
            <solid android:color="#FFFFFF"/>
        </shape>
        

        如果你理解了这段代码,我必须说这很简单,那么第零位的列表视图项将以蓝色突出显示 5 秒钟,然后它会慢慢淡化为白色。

        【讨论】:

          【解决方案8】:

          最简单的

          View updatedview=null;
          
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          
              //these two lines of code means that only one item can be selected at a time
              if(updatedview != null)
                  updatedview.setBackgroundColor(Color.TRANSPARENT);
              updatedview=view;
          
              Toast.makeText(getApplicationContext(), " " + str[position],Toast.LENGTH_LONG).show();
              view.setBackgroundColor(Color.CYAN);
          }
          

          【讨论】:

          • 当用户滚动时,这会产生问题,除非为每一行明确设置/重置背景颜色。因此,这不是一个好的解决方案
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-09-24
          • 1970-01-01
          • 1970-01-01
          • 2019-02-14
          • 1970-01-01
          • 2012-01-22
          • 2011-05-23
          相关资源
          最近更新 更多