android – 在屏幕上处理片段重复旋转(带示例代码)

前端之家收集整理的这篇文章主要介绍了android – 在屏幕上处理片段重复旋转(带示例代码)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有一些类似的答案,但不是这种情况.

我的情况很简单.

我有一个具有两种不同布局的活动,一个在Portrait中,另一个在Landscape中.

在Portrait中,我使用< FrameLayout>并动态地将Fragment添加到其中.

在Landscape中,我使用< fragment>所以片段是静态的. (事实上​​这没关系)

它首先在Portrait中开始,然后我简单地添加了片段:

ListFrag listFrag = new ListFrag();
getSupportFragmentManager().beginTransaction()
        .replace(R.id.FragmentContainer,listFrag).commit();

其中ListFrag扩展了ListFragment.

然后我做一个屏幕旋转.我发现listFrag正在横向模式下重新创建.
(其中我注意到使用非null Bundle再次调用onCreate()方法)

我尝试使用setRetainInstance(false),就像@NPike在this post中说的那样.但是默认情况下getRetainInstance()已经是假的.它没有按照the docs所说的那样做.有人可以解释一下吗?

我正在处理的片段是ListFragment,它在onCreate()中执行setListAdapter().所以if (container == null) return null; method不能在这里使用. (或者我不知道如何申请).

我从this post得到了一些提示.我应该使用if(bundle!= null)setListAdapter(null); else setListAdapter(new …);在我的ListFragment中?但是,当它被销毁/分离时,是否有更好的方法删除/删除片段,而不是在创建时间内执行它? (所以if(container == null)返回null;方法)

编辑:

我找到的唯一简洁方法是执行getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit();在onSaveInstanceState()中.但它会引发另一个问题.

>当屏幕被部分遮挡时,如WhatsApp或TXT对话框弹出,片段也会消失. (这是相对较小的,只是视觉问题)
>当屏幕旋转时,活动将被完全销毁并重新创建.所以我可以在onCreate(Bundle)或onRestoreInstanceState(Bundle)中重新添加片段.但是在(1)的情况下,以及切换活动时,当用户返回我的Activity时,onCreate(Bundle)和onRestoreInstanceState(Bundle)都不会被调用.我无处可重新创建Activity(并从Bundle中检索数据).

对不起,我没有说清楚,我已经做出了决策,getSupportFragmentManager()… replace(…).commit();线仅在纵向模式下运行.

示例代码

我已经提取了简单的代码,以便更好地说明情况:)

MainActivity.java

package com.example.fragremovetrial;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (findViewById(R.id.FragmentContainer) != null) {
            System.out.println("-- Portrait --");       // Portrait
            ListFrag listFrag = new ListFrag();
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.FragmentContainer,listFrag).commit();
        } else {
            System.out.println("-- Landscape --");      // Landscape
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (findViewById(R.id.FragmentContainer) != null) {
            System.out.println("getRetainInstance = " +
                    getSupportFragmentManager().findFragmentById(R.id.FragmentContainer).getRetainInstance());
        }
    }
}

布局/ activity_main.xml中

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/FragmentContainer"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

layout-land / activity_main.xml(无所谓)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
</LinearLayout>

ListFrag.java

package com.example.fragremovetrial;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.widget.ArrayAdapter;

public class ListFrag extends ListFragment {
    private String[] MenuItems = { "Content A","Contnet B" };

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

        System.out.println("ListFrag.onCreate(): " + (savedInstanceState == null ? null : savedInstanceState));

        setListAdapter(new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,MenuItems));
    }
}

请注意我得到以下内容

调试消息

— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false

(rotate Port -> Land)

ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@4052dd28}]
— Landscape —
PrevIoUsly focused view reported id 16908298 during save,but can’t be found during restore.

(rotate Land -> Port)

ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@405166c8}]
— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false

(rotate Port -> Land)

ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@4050fb40}]
— Landscape —
PrevIoUsly focused view reported id 16908298 during save,but can’t be found during restore.

(rotate Land -> Port)

ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@40528c60}]
— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false

当屏幕保持旋转时,创建的片段数量不会无限增加,这是我无法解释的. (请帮忙)

解决方法

我终于提出了一个解决方案,以防止在重新创建Activity时重新创建不需要的Fragment.这就像我在问题中提到的那样:

The only neat way i found is doing getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit(); in onSaveInstanceState(). But it will raise another problems…

……有一些改进.

在onSaveInstanceState()中:

@Override
protected void onSaveInstanceState(Bundle outState) {
    if (isPortrait2Landscape()) {
        remove_fragments();
    }
    super.onSaveInstanceState(outState);
}

private boolean isPortrait2Landscape() {
    return isDevicePortrait() && (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
}

而isDevicePortrait()就像:

private boolean isDevicePortrait() {
    return (findViewById(R.id.A_View_Only_In_Portrait) != null);
}

*请注意,我们不能使用getResources().getConfiguration().orientation来确定设备当前是字面上的肖像.这是因为在屏幕旋转后,Resources对象会更改 – 即使在调用onSaveInstanceState()之前!

如果我们不想使用findViewById()来测试方向(由于任何原因,并且它不是那么整洁),请保留一个全局变量private int current_orientation;并通过current_orientation = getResources()初始化它.getConfiguration().orientation;在onCreate()中.这似乎更整洁.但是我们应该注意不要在Activity生命周期中的任何地方改变它.

*确保我们在super.onSaveInstanceState()之前删除了remove_fragments().

(因为在我的情况下,我从布局和活动中删除碎片.如果它在super.onSaveInstanceState()之后,布局将已经保存到Bundle中.然后碎片也将在之后重新创建.活动重新创建.###)

###我已经证明了这一现象.但What to determine a Fragment restore upon Activity re-create?的原因仅仅是我的猜测.如果您对此有任何想法,请回答my another question.

猜你在找的Android相关文章