片段视图状态在屏幕旋转

时间:2014-08-27 06:52:58

标签: android

当用户点击列表中的项目时,我会加载一些片段。假设用户已单击列表中的第二项,则加载第二个片段。但是,在旋转屏幕时,列表中的第一个片段会被加载。如何在用户旋转屏幕时确保加载相同的片段。 这就是我加载片段的方式

private void selectItem(position) {
    Fragment fragment = null;    
    switch (position) {
        case 0:
            fragment = new FirstFragment();
            break;
        case 1:
            fragment = new SecondFragment();
            break;
        case 2:
            fragment = new ThirdFragment();
            break;
         default:
            break;
     }
    if (fragment != null) {
        android.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
    } 
    else {
        Log.e("NavigationActivity", "Error in creating fragment");
    }
}

我在活动的selectItem(0)中呼叫onCreate

3 个答案:

答案 0 :(得分:2)

整个活动在轮换期间被破坏并重新创建。因此,如果您在Activity.onCreate中调用setItem(0),那么您将始终在内容框架中获得FirstFragment。

似乎很容易就是检测你是否已经在onCreate中设置了一个片段并且没有加载默认值。使用onSaveInstanceState和/或将片段标记为保留。

除了初始加载之外,我对保留的片段或片段管理没有太多经验,因此只需使用onSaveInstanceState来跟踪加载哪个片段似乎是合适的。

在您的Activity中,覆盖onSaveInstanceState:

@Override
public void onSaveInstanceState(Bundle bundle)
{
    bundle.putInt("which_fragment", _fragmentId);
    super.onSaveInstanceState(bundle);
}

其中_fragmentId只是您要加载的特定片段的一些数字标识符。它甚至可能是它的布局ID。在selectItem方法中设置此值。

然后在onCreate:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    _fragmentId = 0;
    if (savedInstanceState != null)
    {
        _fragmentId = savedInstanceState.getInt("which_fragment", 0);
    }

    ...

    selectItem(_fragmentId);
}

答案 1 :(得分:2)

首先,我不会使用positionOnTheList->Fragment依赖。我会依赖一些id(最终或来自资源)。

其次,我认为当你从列表中选择项目时,你不应该创建每个Fragment类的新实例。

你应该考虑这种方法:

Fragment f = fragmentManager.findFragmentById( String.valueOf(id) );
if( f == null )
    f = new FragmentDependingOnId();
mCurrentlySelectedId = id;
fragmentManager.beginTransaction()
            .replace( R.id.container, f , String.valueOf(id))
            .commit();

添加以下方法:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(SELECTED_ID, mCurrentlySelectedId);
}

并在onCreate添加:

if(savedInstanceState!=null){
    mCurrentlySelectedId = savedInstanceState.getInt(SELECTED_ID);
    selectItem(mCurrentlySelectedId);
}

答案 2 :(得分:1)

使用片段时,您通常会使用onCreateView来扩充您的布局。然后使用onActivityCreated来完成初始化列表视图等所需的所有内容......

在您的情况下,您遇到的问题是您应该使用saveInstanceState来跟踪是否加载了片段,因为片段是在每次轮换时重新创建的。

让我们看看一些代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    return inflater.inflate(R.layout.your_fragment_layout, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        //do nothing if the state already exists
    } else {
        //do something if state already exists
    }
}

请注意,如果您需要保存给定值,例如布尔值,您可以使用

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(YOUR_BOOL_TAG, mYourBooleanVar);
}

并使用

将其恢复到onCreateView
mYourBooleanVar= savedInstanceState.getBoolean(YOUR_BOOL_TAG);

同样适用于其他类型。

修改

我没有回答你的问题,所以我提出了更多细节。上面的代码在片段中。但是对于你的问题,在activity你需要类似的东西。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState == null) {
        //here is the transaction to load your first fragment
    }
}

并且你的第一个fragement每次都不会重新加载。

第一次savedInstanceState为空并设置默认片段。然后,每次旋转savedInstanceState时都不为空,并且您的默认片段不会重新加载,而是当前存在的片段。

只有这段代码与您相关,但我将EDIT上方的代码留给了其他人,以防它们对他们有用。