【问题标题】:Android:To set an item as selected when the ListView opens?Android:要在 ListView 打开时将项目设置为选中?
【发布时间】:2011-04-22 17:28:04
【问题描述】:

一个 Activity 有一个 Button 和一个 ListView。 最初,只有 Button 是可见的。按下按钮时,将显示 ListView。 显示时,我是否可以将一个特定项目显示为选中/聚焦?

一个用例可能是假设它是一个语言设置列表,当列表打开时,当前选择的语言必须突出显示。

如果我知道item的索引,如何设置为聚焦显示?

【问题讨论】:

    标签: android android-listview focus listviewitem


    【解决方案1】:

    我正在使用适配器并且不想设置自定义背景颜色,但使用可绘制 xml 中的 android:state_selected。 SetSelection 对我不起作用,但也许这也是因为我需要 SetNotifyDataChanged 这表明 Selected State 不是持久的。

    我还发现 ListView 中某个项目的 Selected 状态不是持久的,因为 SetNotifyDataChanged 会导致更新 ListView 布局,从而将它们全部清除。在 Adapter 的 GetView 中将项目设置为 Selected 也为时过早。

    最终,在更改列表视图的布局后,我为所选项目的视图设置了 Selected 状态,这是触发 LayoutChange 事件的时间(在 Java 中,它可能将 a 附加到 ListView 的 OnLayoutChangeListener)。

    为了方便起见,我将所选项目的视图存储为适配器的 SelectedItemView。 在 ListView 的 LayoutChange 事件处理程序中,我只是将适配器的 SelectedItemView.Selected 设置为 true。

    这是我的 Activity 中的代码,我在其中为 ListView 设置了 Adapter 并订阅了 LayoutChange(或在 Java 中附加一个 OnLayoutChangeListener)

            ringTonesListView.Adapter = ringTonesListAdapter;
            ringTonesListView.LayoutChange += (s, layoutChangeArgs) => {
                //At this stage the layout has been updated and the Selected can be set to true for the view of the selected item. This will result in android:state_selected logic to be applied as desired and styling can be completely done per layout in Resources.
                ringTonesListAdapter.SelectedItemView.Selected = true;
            };
    

    这是我的适配器代码:

    public class RingTonesListAdapter : BaseAdapter<RingToneItem>
    {
        List<RingTone> Items { get; set; }
    
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;
    
            // re-use an existing view, if one is available
            // otherwise create a new one
            if (view == null)
            {
                view = Context.LayoutInflater.Inflate(Resource.Layout.AlertSoundItem, parent, false);
                view.Click += SelectRingTone;
            }
    
            RingTone ringTone = this[position];
            if (ringTone.Selected)
            {
                //==> Important
                //Store this view since it's the view for the Selected Item
                SelectedItemView = view;
                //Setting view.Selected to true here doesn't help either, since Selected will be cleared after.
            }
    
            return view;
        }
    
        private void SelectRingTone(object sender, EventArgs args)
        {
            View view = (View)sender;
            string title = view.FindViewById<TextView>(Resource.Id.ringToneTitle).Text;
            RingToneItem ringToneItem = Items.First(rt => rt.Title == title);
            if (!ringToneItem.Selected)
            {
                //The RingTone was not selected and is selected now
                //Deselect Old and Select new
                foreach (RingToneItem oldItem in Items.Where(rt => rt.Selected))
                {
                    oldItem.Selected = false;
                }
    
                // Select New RingTone
                ringToneItem.Selected = true;
                //Update the ListView. 
                //This will result in removal of Selected state for all Items when the ListView updates it's layout
                NotifyDataSetChanged();
            }
    
            //Now play the test sound
            NotifierService.TestSound(Context, ringToneItem);
        }
    
        public View SelectedItemView { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      如果您为您的ListView 使用Adapter,请将此代码添加到您的适配器:

      public class MyAdapter extends ArrayAdapter<MyClass> {
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              if (convertView == null) {
                  LayoutInflater inflator = (LayoutInflater) getContext()
                          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                  rowView = inflator.inflate(R.layout.my_adapter, null);
              } else {
                  rowView = (View) convertView;
              }
      
              //...
      
              // set selected item
              LinearLayout ActiveItem = (LinearLayout) rowView;
              if (position == selectedItem){
                  ActiveItem.setBackgroundResource(R.drawable.background_dark_blue);
      
                  // for focus on it
                  int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
                  ((ListView) parent).setSelectionFromTop(position, top);
              }
              else{
                  ActiveItem.setBackgroundResource(R.drawable.border02);
              }    
          }
      
          private int selectedItem;
      
          public void setSelectedItem(int position) {
              selectedItem = position;
          }    
      }
      

      在你的Activity:

      myAdapter.setSelectedItem(1);
      

      【讨论】:

        【解决方案3】:

        我发布我的解决方案,因为谷歌仍然不知道答案。

        getListView().setItemChecked(selectedGroupIndex, true);
        

        【讨论】:

        • 投票 +1 以接受此帖子作为答案,而不是 setSelection
        • 这对我不起作用,你能详细说明一下吗?这在 2018 年仍然有意义吗?
        • @DanChaltiel 我刚刚对其进行了测试,它以某种方式工作(S9,Android 8.0)。从我所看到的myListView.setItemChecked(-1,true); 仍然将指针设置为“-1”,这也是myListView.getCheckedItemPosition(); 将返回的值,但不幸的是它似乎没有将实际项目标记为选中(= 给它其他背景颜色)。不知道该怎么做,但我可以告诉你的是,如果你使用的是触摸屏设备,你必须使用“检查”方法,因为像 getSelectedItemPositionsetSelection 这样的其他方法不能正常工作。
        【解决方案4】:

        简而言之,ListView::setSelection(int position) 就是您所需要的。但是,根据设备是否处于触摸模式,它可能有也可能没有视觉效果(背景突出显示)。更多详情请参考Android ListView Selection Problem

        【讨论】:

        • 不,setSelection(pos) 不能解决我的问题!该设备未处于触摸模式,但我仍然没有得到背景突出显示。我只是在模拟器上测试。我的列表视图正在使用选择器 xml,希望对此没有影响!
        • 你怎么知道你的设备没有处于触摸模式?也许您可以尝试使用导航键突出显示按钮并使用中心键按下按钮。看看这是否有所作为。
        • 我现在只是在 Eclipse 中使用模拟器。并使用我 PC 的键盘进行操作。
        • 你是怎么按下按钮的?你是用鼠标还是只用键盘?
        • 尝试添加两行:listView.setFocusable(true); listview.setFocusableInTouchMode(true);
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多