使用 Cursor Loader 选择 ListView 中的第一项

Posted

技术标签:

【中文标题】使用 Cursor Loader 选择 ListView 中的第一项【英文标题】:Select first item in ListView with Cursor Loader 【发布时间】:2014-12-12 12:11:49 【问题描述】:

我有一个 android 应用程序(在平板电脑上)使用主-详细信息流在左侧显示预测列表,在右侧显示详细信息。我希望能够在应用程序加载时选择第一项。

我在onLoadFinished 方法中有设置选定索引的代码。我实现了这一点,因为有时用户会选择一个项目,如果他们改变了方向,它就会离开屏幕。我使用以下方法来确保在加载后再次选择正确的项目:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
    mForecastAdapter.swapCursor(data);

    // If we have a selected index - select it.
    if(mSelectedIndex != ListView.INVALID_POSITION) 
        mForecastListView.setSelection(mSelectedIndex);
    

我尝试添加一个 else 语句来检查是否正在使用平板电脑,以选择第一项。代码已执行,但似乎发生在实际加载列表视图并且未选择项目之前。打开应用时,我应该将代码放在哪里以选择第一项?

编辑 这是我尝试过的一种方法,但没有成功:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
    mForecastAdapter.swapCursor(data);

    // If we have a selected index - select it.
    if(mSelectedIndex != ListView.INVALID_POSITION) 
        mForecastListView.setSelection(mSelectedIndex);
     else if(mForecastAdapter.IsTwoPane())
        mForecastListView.setSelection(0);
    

【问题讨论】:

您是否有理由交换而不是更改光标? 如果我没记错的话,我相信你在使用 CursorLoader 时需要使用它。不过,我认为这与我需要做的事情无关。 交换和更改功能略有不同,前者保留前一个光标而不关闭它,而后者关闭前一个光标并用新的光标替换它。 适配器发生变化后,你是否在调用 notifyDataSetChanged()? 是的。在内容提供程序文件中,经过任何更改后我有getContext().getContentResolver().notifyChange(uri, null);notifyDataSetChange 有什么区别? 【参考方案1】:

我会执行以下操作,我已经为列表视图完成了一般操作,也应该与游标一起使用。

在您的适配器中,为所选位置创建一个字段

public int selectedPos = 0;//use setter/getter eventually

现在确保您的 listView 的 OnItemClickListener/OnItemSelectedListener 执行以下操作:

<YOUR_ADAPTER_INSTANCE>.selectedPos = positionSelected;

最后,在getView() 中为您的适配器执行以下操作:

if(position == selectedPos) 
   //do what you want to show selection
 else 
   //do what you want for default state of the list items

这将确保在第一次显示列表时, selectedPos 将为 0,因此将根据上述选择第一个位置。

如果您想通过orientationChange 等方式保持用户的选择,您只需要确保在“恢复”后将信息传递给适配器。

【讨论】:

所以你认为代码不属于onLoadFinished?或者在 onLoadFinished 中处理方向变化的东西(因为它在哪里,我知道这是可行的)并处理适配器中的默认选择是否会被破解? OnLoadFinished 应该只是交换光标(或像有人提到的那样替换)......这应该自动重新布局。然后应该像我建议的那样处理选定的部分。告诉我。 不走运。我首先需要 onLoadFinished 中的代码来处理我想要的,getView 没有帮助。【参考方案2】:

如果您由于配置更改而尝试恢复列表视图,也许保存状态会有所帮助?例如:

private Parcelable mForceastListViewSavedState;
private int mForecastListViewPositionSavedState;
private static final String sForecastListViewSavedStateKey = "ForecastListViewSavedState";
private static final String sForecastListViewPositionSavedState = "ForecastListViewPositionSavedState";

@Override
public void onSaveInstanceState(Bundle outState) 
    if(mForecastListView != null)
        outState.putParcelable(sForecastListViewSavedStateKey, mForecastListView.onSaveInstanceState());
        outState.putInt(sForecastListViewPositionSavedState, mForecastListView.getFirstVisiblePosition());
    
    super.onSaveInstanceState(outState);


@Override
public void onActivityCreated(Bundle savedInstanceState) 
    ...

    //Restore InstanceState
    if (savedInstanceState != null)
        mForceastListViewSavedState = savedInstanceState.getParcelable(sForecastListViewSavedStateKey);
        mForecastListViewPositionSavedState = savedInstanceState.getInt(sForecastListViewPositionSavedState);
    


@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
    mForecastAdapter.swapCursor(data);

    //Restore ListView State
    if (mForceastListViewSavedState != null)
        mForecastListView.onRestoreInstanceState(mForceastListViewSavedState);
        mForecastListView.setSelection(mForecastListViewPositionSavedState);
    

【讨论】:

我确实使用 onSaveInstanceState 来存储所选位置以处理方向更改。然后,在 onLoadFinished() 我调用集合选择。这在用户旋转设备时有效。出于某种原因,当应用首次打开时 setSelection(0) 不会选择第一项。【参考方案3】:

我解决了这个问题,虽然这个问题已经过时了。我的解决方案是:

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader,Cursor cursor)

    mForecastAdapter.swapCursor(cursor);
    if(mPositon!=ListView.INVALID_POSITION)
        mListView.smoothScrollToPosition(mPositon);
    else if(mTwoPane)
        
            new Handler().post(new Runnable() 
                @Override
                public void run() 
                    mListView.performItemClick(mListView, 0, mListView.getAdapter().getItemId(0));                        
            );
        
    

【讨论】:

这看起来是一个非常好的解决方案!我已经有一段时间没有为此碰过我的代码了,但是您是否验证过这在应用程序第一次打开时是否有效? 做得很好。用这个,我解决了问题。另外,还要判断device的状态。mTwoPane是你需要知道和使用的语句。

以上是关于使用 Cursor Loader 选择 ListView 中的第一项的主要内容,如果未能解决你的问题,请参考以下文章

QML ListView Loader 不需要的预定义行为

分页列表和 CursorLoader

Flutter ListVİew 总是在向上或向下滚动时重新渲染

使用 Zend_Loader 选择不同版本的 Zend Framework 加载及其问题

SQL*Loader 加载数据问题,创建了.ctl 文件,在执行sqlldr命令之后出现找不到文件

`/deep/` 选择器无法在我的 VueJS 应用程序中使用 sass-loader