gpt4 book ai didi

android - backstack 中的配置更改 fragment 现在共享 FrameLayout 后?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:49:14 26 4
gpt4 key购买 nike

应用程序问题:

当方向改变时,应用会遇到这些问题:

  • FragmentA 和 FragmentC 现在都占用了 FrameLayout 容器。

有效的方法:在旋转屏幕之前,一切都按我希望的方式工作。

Activity 简述:

EditActivity 目的:编辑集合和项目字段。

此 Activity 以编程方式创建的 fragment :

  • FragmentA - 用于编辑集合字段的 fragment
  • FragmentB - 集合中项目的 ListFragment
  • FragmentC - 用于编辑项目字段的 fragment 。

初始布局:FragmentA 位于 FragmentB 之上,每个都有自己的 FrameLayouts。

当用户单击 FragmentB 的 ListView 项目时:将 FragmentA 替换为 FragmentC 以允许用户编辑该项目的字段。现在 FragmentC 位于 FragmentB 之上。

这似乎是一个非常简单的概念: Activity 的顶部用于编辑整个集合的属性或编辑集合中的单个项目。我觉得我在布局方面没有做任何奇妙的事情,所以我有点困惑,手机(模拟器)的简单旋转会导致这些问题,而我正费尽心机地尝试修复这些问题。

为什么 Android Fragment Guide example对我不起作用:他们的例子很像我正在做的,但他们的细节 fragment 要么在新 Activity 中打开,要么在当前 Activity 中的自己的框架中打开,他们不做任何 fragment 交换,所以我不能了解他们将如何使用 onSaveIstanceState 来保留可见的 fragment ,然后在 onCreate 中使用该信息来重新创建方向更改之前的 UI。

编辑:通过将 listfragment 放入 XML 中解决了一个问题,这解决了永久旋转的“加载...”问题。

最佳答案

已解决。哦,我走过的兔子洞……无论如何,如果您遇到这样的问题,需要考虑以下几点:

  • 最终我不必在 onSaveInstanceState(Bundle outState) 中编写任何代码。
  • 最终,我不必考虑在 onSaveInstanceState 中处理后台堆栈或在 Activity 的 onCreate 中处理它。
  • 当第一次以编程方式将 fragment “添加”到 FrameLayout 时,使用 replace 而不是 `add' - 这可能是我遇到麻烦的根源之一。
  • 在 onCreate 中检查 savedInstanceState 的 bundle 是否为 null,if(savedInstanceState == null),如果是,那么我知道该 Activity 之前没有因配置更改而被拆除,所以在这里,我构建了应该在 Activity 启动时立即显示的 fragment 。以编程方式在别处激活的其他 fragment (即,晚于 Activity 的 onCreate()),它们不属于 if,它们属于 其他:
  • else onSaveInstanceState != null 我知道这个东西不为 null 的原因只有一个,因为系统在 onSaveInstanceState(Bundle outState) 中创建了一个名为 outState 的 bundle 并 hucked它在 Activity 的 onCreate 方法中,我现在可以在其中获取我的 grubbies。所以在这里我知道一些事情:
    1. 确定我在 Activity 的 onCreate 中创建的 fragment 仍然是 Activity 的一部分(我没有分离或销毁它们),但是,我不能对于通过用户的操作赋予生命的 fragment 的相同声明,这些 fragment 当前可能会或可能不会(在方向也就是配置更改时)附加到 Activity 。
    2. 这是放置 if-this-thing-is-attached 子句的好地方。我最初搞砸的一件事是我没有给所有以编程方式添加的 fragment 一个标签;给所有以编程方式添加的 fragment 标签。然后,我可以通过 savedInstanceState.containsKey(MY_FRAG_TAG)getFragmentManager().findFragmentByTag(MY_FRAG_TAG)
    3. 确定 savedInstanceState 包是否包含该 key

所以这是 Activity 的 onCreate(简化):

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

// ...omitted code...

if(savedInstanceState == null){
// create fragment for collection edit buttons
editCollection = FragmentA.newInstance(someVariable);

// programmatically add fragment to ViewGroup
getFragmentManager().beginTransaction().replace(R.id.edit_topFrame, editCollection, EDIT_COLLECTIONS_TAG).commit();


}
// else there be stuff inside the savedInstanceState bundle
else{
// fragments that will always be in the savedInstanceState bundle
editCollectionFragment = (FragmentA)getFragmentManager().findFragmentByTag(EDIT_COLLECTIONS_TAG);

// fragments that may not be in the bundle
if(savedInstanceState.containsKey(EDIT_ITEM_TAG)){
editItemFragment = (FragmentC)getFragmentManager().getFragment(savedInstanceState, EDIT_ITEM_TAG);
}

}

// This fragment is NOT programmatically added, ie, it is statically found in an XML file.
// Hence, the system will take care of preserving this fragment on configuration changes.
listFrag = (ListViewFragment)getFragmentManager().findFragmentById(R.id.ListFragment);


// create adapter
adapter = new EditCursorAdapter(this, null);

// set list fragment adapter
listFrag.setListAdapter(adapter);

// prepare the loader
getLoaderManager().initLoader(LOADER_ID, null, this);
}

Activity 的列表 fragment 监听器,其中 FragmentC 被替换为 FragmentA:

// listfragment listener
@Override
public void listFragListener(Cursor cursor) {

// checking backstack size
Log.d(TAG, SCOPE +"backstack size: "+getFragmentManager().getBackStackEntryCount());

// With each listview click there should be only one item in the backstack.
getFragmentManager().popBackStack();

// create new fragment
editItemFragment = FragmentC.newInstance(cursor);

// programmatically add new fragment
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.edit_topFrame, editItemFragment, EDIT_ITEM_TAG);
ft.addToBackStack("pop all of these"); // was testing different ways of popping
ft.commit();

// interesting: this reports the same value as the first log in this method.
// ...clearly addToBackStack(null).commit() doesn't populate the backstack immediately?
Log.d(TAG, SCOPE +"backstack size: "+getFragmentManager().getBackStackEntryCount());
}

而 onSaveInstanceState 就像一只松鸦一样赤裸:

    @Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

}

总结:我的 Activity 完全按照我想要的方式运行。

现在,如果我有一个 bunch 添加的 fragment ,那么我可能会以更编程的方式处理它们,而不是通过硬编码 if(savedInstanceState.contains(*hard coded key* )。我对此进行了一些测试,但无法证明其有效性,但是对于外面的人来说,这可能会激发您可以做什么的想法:

  1. 创建一个私有(private)的添加 fragment 集:

    // Collection of Frag Tags
    private Set<String> AddedFragmentTagsSet = new HashSet<String>();
  2. onAttachFragment 中执行如下操作:

    @Override
    public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    // logging which fragments get attached and when
    Log.d(TAG, SCOPE +"attached fragment: " +fragment.toString());

    // NOTE: XML frags have not frigg'n tags

    // add attached fragment's tag to set of tags for attached fragments
    AddedFragmentTagsSet.add(fragment.getTag());

    // if a fragment has become detached remove its tag from the set
    for(String tag : AddedFragmentTagsSet){
    if(getFragmentManager().findFragmentByTag(tag).isDetached()){
    AddedFragmentTagsSet.remove(tag);
    }
    Log.d(TAG, SCOPE +"contents of AddedFragmentTagsSet: " +tag);
    }
    }
  3. 然后在 Activity 的 onCreatesavedInstanceState 子句中:

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

    // ...omitted code...

    if(savedInstanceState == null){
    // create fragment for collection edit buttons
    editCollection = FragmentA.newInstance(someVariable);

    // programmatically add fragment to ViewGroup
    getFragmentManager().beginTransaction().replace(R.id.edit_topFrame, editCollection, EDIT_COLLECTIONS_TAG).commit();


    }
    // else there be stuff inside the savedInstanceState bundle
    else{
    // fragments that will always be in the savedInstanceState bundle
    editCollectionFragment = (FragmentA)getFragmentManager().findFragmentByTag(EDIT_COLLECTIONS_TAG);

    //////////// find entries that are common to AddedFragmentTagsSet & savedInstanceState's set of keys ///////////

    Set<String> commonKeys = savedInstanceState.keySet();
    commonKeys.retainAll(AddedFragmentTagsSet);

    for(String key : commonKeys){
    editItemFragment = FragmentC)getFragmentManager().getFragment(savedInstanceState, key);

    }
    }
    }

...但这未经测试,仅用于激发创意;在试图弄清楚我的 Activity 对配置更改的处理有什么问题时,我确实在这个方向上跌跌撞撞,并认为它可能会为合适的人带来成果;虽然最终,显然,这次我找到了一种更简单的方法来解决我的问题。

关于android - backstack 中的配置更改 fragment 现在共享 FrameLayout 后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16740721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com