如何在 orientation/configuration 更改后保持 ListView 片段状态?
How to maintain ListView fragment state after orientation/configuration change?
我的应用程序中有一个 ListView 片段遇到了一些问题。
- 当我滚动到列表视图中的特定元素,然后旋转设备时,列表视图重置到列表顶部。
- 当我在列表视图中进入多 select 模式,然后旋转设备时,selected 列表项重置。
这是我的 activity:
public class TestActivity extends ActionBarActivity
{
protected static final String FRAGMENT_TAG = "TEST";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FragmentManager fm = getFragmentManager();
TestFragment f = (TestFragment)fm.findFragmentByTag(FRAGMENT_TAG);
// If no fragment exists, then create a new one and add it!
if (f == null)
{
fm.beginTransaction().add(R.id.fragment_holder, new TestFragment(), FRAGMENT_TAG)
.commit();
}
}
}
这里是main_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize" >
</android.support.v7.widget.Toolbar>
<FrameLayout
android:id="@+id/fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这是我的 TestFragment class,还有杂项。删除的内容:
public class TestFragment extends ListFragment
{
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// Sets the list up for multiple choice selection.
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(this);
}
}
我看到了两个关于这个的讨论。一个是声明我应该在片段的 onCreate(Bundle savedInstanceState)
方法中使用 setRetainInstance(true)
。另一个说我应该使用 onSaveInstanceState(Bundle bundle)
和 onRestoreInstanceState(Bundle bundle)
方法以某种方式跟踪内容。我想使用 setRetainInstanceState(true)
方法,但像这样将其添加到项目中:
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstanceState(true);
}
对我不起作用。我在这里做错了什么?
我建议使用一种略有不同的方法将 Fragment
添加到您的 Activity
。
在你的 TestActivity
class 中,检查 onCreate() 方法中的 Bundle
是否为 null。如果 savedInstanceState 为空,则仅添加 Fragment
。这将防止您的 Activity
在设备方向改变时添加相同 Fragment
的另一个实例。
public class TestActivity extends ActionBarActivity {
protected static final String FRAGMENT_TAG = "TEST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.fragment_holder, new TestFragment(), FRAGMENT_TAG)
.commit();
}
}
}
我建议不要对具有 UI 的 Fragment
使用 setRetainInstance(true)
方法。查看 Whosebug 讨论 here 以了解何时使用 setRetainInstance(true)
.
我的应用程序中有一个 ListView 片段遇到了一些问题。
- 当我滚动到列表视图中的特定元素,然后旋转设备时,列表视图重置到列表顶部。
- 当我在列表视图中进入多 select 模式,然后旋转设备时,selected 列表项重置。
这是我的 activity:
public class TestActivity extends ActionBarActivity
{
protected static final String FRAGMENT_TAG = "TEST";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FragmentManager fm = getFragmentManager();
TestFragment f = (TestFragment)fm.findFragmentByTag(FRAGMENT_TAG);
// If no fragment exists, then create a new one and add it!
if (f == null)
{
fm.beginTransaction().add(R.id.fragment_holder, new TestFragment(), FRAGMENT_TAG)
.commit();
}
}
}
这里是main_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize" >
</android.support.v7.widget.Toolbar>
<FrameLayout
android:id="@+id/fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这是我的 TestFragment class,还有杂项。删除的内容:
public class TestFragment extends ListFragment
{
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// Sets the list up for multiple choice selection.
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(this);
}
}
我看到了两个关于这个的讨论。一个是声明我应该在片段的 onCreate(Bundle savedInstanceState)
方法中使用 setRetainInstance(true)
。另一个说我应该使用 onSaveInstanceState(Bundle bundle)
和 onRestoreInstanceState(Bundle bundle)
方法以某种方式跟踪内容。我想使用 setRetainInstanceState(true)
方法,但像这样将其添加到项目中:
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstanceState(true);
}
对我不起作用。我在这里做错了什么?
我建议使用一种略有不同的方法将 Fragment
添加到您的 Activity
。
在你的 TestActivity
class 中,检查 onCreate() 方法中的 Bundle
是否为 null。如果 savedInstanceState 为空,则仅添加 Fragment
。这将防止您的 Activity
在设备方向改变时添加相同 Fragment
的另一个实例。
public class TestActivity extends ActionBarActivity {
protected static final String FRAGMENT_TAG = "TEST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.fragment_holder, new TestFragment(), FRAGMENT_TAG)
.commit();
}
}
}
我建议不要对具有 UI 的 Fragment
使用 setRetainInstance(true)
方法。查看 Whosebug 讨论 here 以了解何时使用 setRetainInstance(true)
.