0

TL;DR:が をリサイクルしているときと を交換しているときRecyclerViewの の呼び出しを区別できません。onBindViewHolderViewFragment

ここSOで答えを探すのに多くの時間を費やしましたが、結局何もうまくいきませんでした。それがしたことは、答えはおそらく を使用することにあると教えてくれましたが、savedInstanceStateうまく使用できませんでした。

構造 :

  • メインフラグメント
    • メインビュー
    • SwitchFragmentButton

MainViewは がありFrameLayout、 を保持するために使用されますFragment

最初のFragmentものは重要ではありませんが、2 番目Fragmentのものは でありOverviewFragment、その構造は次のとおりです。

  • 概要フラグメント
    • RecyclerView
      • CustomItemView
        • テキストビュー
        • ChangeTextColorButton
        • アイテムの削除ボタン
        • ...
    • AddItemButton

RecyclerViewリストを水平にする必要があり、それが最も簡単な方法であるため、を使用しています。

望ましい動作:

ボタンを2回クリックしたとき(フラグメントを変更して元に戻すとき)に色の変更を保持したいのですが、リストからアイテムを削除してから再度追加したときは保持しません。

問題 :

色は常に保持されるか、まったく保持されません。onBindViewHolderのアダプターでテキストの色を設定するために使用RecyclerViewすると、バインドがフラグメントの置換 (変更された色を復元する場所) によるものか、ビューのリサイクル (復元しない場所) によるものかを区別できません。

コード :

SwitchFragmentButtonのメソッドOnClickListenerを呼び出します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 */
}

RecyclerViewAdapter定義は次のとおりです。

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 */
    }
}

MyItemここに CustomItemView のコア項目があります (すべての MyItem にはその CustomItemView があり、すべての CustomItemView には MyItem があります)

ノート :

minSdkVersion: 19.

編集 :

@goldenb のおかげで、問題が絞り込まれ、2 つの解決策が現れました。

解決策 1 :

フラグメントを置き換える代わりに、それらをすべて追加してから表示/非表示にします。

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ため、状態が維持されます。

ただし、私の質問は、Fragmentの状態を保存して復元する方法に関するものであるため、これを回答として受け入れることはできません。

解決策 2 :

オーバーライドOverviewFragment#onPauseして状態を保存し、 で復元しOverviewFragment#onCreateます。

この解決策はもっともらしいようで、現在調査中です。CustomItemViewただし、データを からに再配置するには、プロジェクトで再構築が必要なMyAdapterため、しばらく時間がかかります。

4

2 に答える 2