当numColumns发生变化时,如何在gridview上保留所选项目突出显示?

时间:2015-01-04 19:17:06

标签: android android-layout android-gridview

我有ActionBarActivity GridView

GridView包含 2列纵向 3列横向。

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

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

我注意到如果我将numColumns保持为纵向和横向相同,它就不会这样做。

我认为此问题在我将活动更改为ActionBarActivity后开始发生,因此可能是一个错误..

任何人都知道为什么或如何解决它?

2 个答案:

答案 0 :(得分:5)

我有一个类似的场景,最后解决了这个问题,即创建一个带有boolean字段的自定义网格项,以跟踪项目是否被选中,然后通过自定义适配器正确突出显示该项目。以下是我所做的大致概述:

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

public boolean getSelectedStatus ()
{
    return selectedStatus;
}

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

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

@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);
        }
    }
});

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

答案 1 :(得分:3)

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

问题分两部分解决。一,适配器必须启用稳定的ID。二,你的适配器实际上必须返回稳定的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时使用。我假设你在这里做。通过返回true,您实际上是在告诉Android根据ID值而不是位置编号跟踪激活(突出显示)的项目。

即使启用了稳定的ID,您也必须实际返回一个在位置变化中唯一且稳定的ID。由于大多数适配器不启用稳定ID,因此它们通常仅返回位置编号作为稳定ID。从技术上讲,如果项目的位置永远不会随时间变化,那么位置编号“可能”将被用作稳定ID。但是,返回稳定/唯一ID的最安全的方法是将一个分配给类对象的类存储在适配器中并从中拉出。