如何在动态添加的片段中将RecyclerView中的自定义View状态保存?

时间:2016-10-28 10:25:28

标签: android android-fragments android-lifecycle fragmenttransaction android-savedstate

TL; DR:RecyclerView回收onBindViewHolder或替换View时,我无法区分FragmentsavedInstanceState的来电。

我确实花了很多时间在这里寻找答案,但最终没有任何效果。它所做的是告诉我答案可能是使用MainView,但我没有成功使用它。

结构:

  • MainFragment
    • 的MainView
    • SwitchFragmentButton

FrameLayout中有一个Fragment,用于存放Fragment

第一个Fragment并不重要,但第二个OverviewFragmentRecyclerView,其结构为:

  • OverviewFragment
    • RecyclerView
      • CustomItemView
        • 的TextView
        • ChangeTextColorButton
        • DeleteItemButton
        • ...
    • AddItemButton

我使用的是onBindViewHolder,因为列表需要水平,这是我发现的最简单方法。

所需行为

我希望在单击按钮两次时保持颜色更改(更改片段然后重新开始),但是当我从列表中删除项目然后再次添加时,我不想保留颜色。

问题:

颜色总是或永远不会保留。使用RecyclerView的适配器中的SwitchFragmentButton设置文本颜色不允许我区分绑定是来自片段替换(我将恢复更改的颜色)还是视图循环(在哪里我不会恢复它)

代码:

OnClickListener的{​​{1}}调用MainView的方法

void switchFragment(Fragment fragment) {
    FragmentManager fm = mainFragment.getChildFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.mainView_fragment_slot, fragment);
    ft.commit();
}

以下是管理(简化)颜色的方式:

public class CustomItemView extends FrameLayout {
    private TextView textView;
    private int color;
    /* other attributes */

    public CustomItemView(/* any default constructor */) {
        super(/* args */);
        init();
    }

    private void init() {
        inflate(getContext, R.layout.custom_item_view, this);
        textView = (TextView) findViewById(R.id.customItemView_text_view);
        ChangeTextColorButton ctcButton = /* ... */;
        /* other views */

        ctcButton.setOnClickListener(new OnClickListener() {
            public void onClick() {
                setColor(getColorWithDialogAndAll());
            }
        }

        resetColor();
    }

    public void resetColor() {
        setColor(0xff0000ff);
    }

    public void setColor(int color) {
        this.color = color;
        textView.setTextColor(color);
    }

    /* other methods */
}

以下是RecyclerView的{​​{1}}定义:

Adapter

public class MyAdapter extends RecyclerView.Adapter { private List<MyItem> myItemList = new LinkedList<>(); public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { MyViewHolder viewHolder = (MyViewHolder) holder; //this is called in both situations viewHolder.customItemView.resetColor(); } /* other methods */ private class MyViewHolder extends RecyclerView.ViewHolder { CustomItemView cutsomItemView; /* constructor, calling super() and setting the attribute */ } } 这里是CustomItemView的核心项目(每个MyItem的CustomItemView和每个CustomItemView都有它的MyItem)

注意:

MyItem:19。

编辑:

感谢@goldenb,问题已经缩小,出现了两个解决方案。

解决方案1:

不是替换片段,而是将它们全部添加,然后显示/隐藏它们。

minSdkVersion

此解决方案在某种程度上有效,但不是解决问题的真正方法。它避免删除void switchFragment(Fragment fragment) { FragmentManager fm = mainFragment.getChildFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.hide(currentFragment); ft.show(R.id.mainView_fragment_slot, fragment); ft.commit(); currentFragment = fragment; } ,因此保留了状态。

但是,我的问题是关于如何保存然后恢复Fragments的状态,所以我不能接受这个作为答案。

解决方案2:

覆盖Fragment以保存状态,并在OverviewFragment#onPause中恢复。

这个解决方案似乎有道理,我正在探索它。但是,我的项目需要进行一些重组,以便将数据从OverviewFragment#onCreate重新定位到CustomItemView,因此需要一些时间。

2 个答案:

答案 0 :(得分:0)

您可以在Activity中使用savedInstancestate或RestoresavedInstancestate,或者在片段中使用共享首选项来存储数据并在回调片段时提取数据

答案 1 :(得分:0)

如果你可以接受选择不破坏View层次结构:

FragmentManager fragmentManager = getFragmentManager()
// Or: FragmentManager fragmentManager = getSupportFragmentManager()
fragmentManager.beginTransaction()
    .remove(fragment1)
    .add(R.id.fragment_container, fragment2)
    .show(fragment3)
    .hide(fragment4)
    .commit();

希望在所有编辑后这有帮助!