当 numColumns 更改时,如何在 gridview 上保留所选项目突出显示?

How do I retain selected item highlighting on gridview when numColumns changes?

我有一个 ActionBarActivity 和一个 GridView

GridView 纵向有 2 列,横向有 3 列。

当我 select 纵向项目(开始我的 ActionMode)然后旋转设备时,selected 项目突出显示向左移动一个项目. 例如,如果我 select 第二个项目并旋转,第一个项目将突出显示。如果我 select 第一个项目并旋转,则不会突出显示任何项目。

代码中的实际 selection 是正确的,只是突出显示是错误的。

我注意到如果我保持纵向和横向的 numColumns 相同,它不会执行此操作。

我认为这个问题是在我将 activity 更改为 ActionBarActivity 之后开始出现的,所以它可能是一个错误..

有人知道为什么或如何解决吗?

我遇到了类似的情况并最终解决了这个问题,即创建一个带有 boolean 字段的自定义网格项目以跟踪该项目是否被选中,然后通过自定义适当地突出显示该项目适配器。以下是我所做工作的粗略概述:

(1) 我创建了一个带有 boolean 字段的自定义网格项,为简单起见,我们将其称为 selectedStatus。我也在我的网格项class中添加了相应的方法来获取选中状态:

public boolean getSelectedStatus ()
{
    return selectedStatus;
}

public void setSelectedStatus (boolean paramSelectedStatus)
{
    this.selectedStatus = paramSelectedStatus;
}

(2) 然后我创建了一个自定义 Adapter extends BaseAdapter 来处理我创建的自定义网格对象。在此 Adapter 中,我检查网格对象的选定状态是否为 truefalse 并相应地突出显示该项目,如下所示:

@Override
public View getView (final int position, View convertView, ViewGroup parent)
{

    // rest of getView() code...

    if (!yourGridObject.getSelectedStatus())
    {
        convertView.setBackgroundColor(Color.TRANSPARENT);
    }
    else
    {
        convertView.setBackgroundColor(Color.LTGRAY);
    }

    // rest of getView() code...

    return convertView;
}

(3) 最后添加onItemClickListener设置选中状态和选中(点击)网格项的背景颜色:

yourGridView.setOnItemClickListener(new OnItemClickListener()
{
    @Override
    public void onItemClick(AdapterView<?> parent, View view, 
            int position, long id)
    {
        YourGridObject yourGridObject = (YourGridObject) parent.getItemAtPosition(position);
        if (!yourGridObject.getSelected())
        {
            view.setBackgroundColor(Color.LTGRAY);
            yourGridObject.setSelected(true);
        }
        else
        {
            view.setBackgroundColor(Color.TRANSPARENT);
            yourGridObject.setSelected(false);
        }
    }
});

以这种方式实现选择可确保在列数和行数交换时网格项目的突出显示(选择)不会改变,因为选择状态包含在网格对象本身中。

您不需要按照 Willis 的建议手动处理项目选择。 Android 完全支持你的要求。我假设您使用的是 ArrayAdapter 但是这个答案适用于所有适配器。请注意,某些适配器(如 CursorAdapter)不会遇到您发布的问题,并且不需要以下解决方案,因为它已经在内部进行了。

问题分两部分解决。第一,适配器必须启用稳定的 ID。第二,您的适配器实际上必须 return 稳定的 ID。您将需要扩展 ArrayAdapter 或您正在使用的任何适配器。然后确保您已定义以下方法,如下所示。

private class MyAdapter extends ArrayAdapter<YourObjects> {
    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public long getItemId(int position) {
        //Return a unique and stable id for the given position
        //While unique, Returning the position number does not count as stable.
        //For example:
        return getItem(position).methodThatReturnsUniqueValue();
    }
}

大多数适配器不启用 hasStableIds。它主要仅在启用 choiceMode 时使用。我假设你在这里做。通过 return 为真,您实际上是在告诉 Android 根据 ID 值而不是位置编号来跟踪已激活(突出显示)的项目。

即使启用了稳定的 ID,您实际上也必须 return 一个在位置变化时唯一且稳定的 ID。由于大多数适配器不启用稳定 ID,因此它们通常只 return 位置编号作为稳定 ID。从技术上讲,如果一个项目的位置从不随时间改变,那么位置编号 "could" 将用作稳定 ID。但是,return stable/unique ID 最安全的方法是将一个分配给存储在适配器中的 class 对象并从中提取。