1

ユーザーがボタンを押して を表示する画面がありDialogFragmentますEditText。情報を入力し、 を押しOkます。もう一度ボタンを押すと、入力しEditTextた情報が表示され、すべて正常に動作するようにしました。

ただし、情報を入力して を押しOk、オプション メニューを使用して別の画面を表示した場合、もう一度ボタンを押すfragmentと、情報は に表示されません。EditText

ユーザーがその画面から一瞬離れても、どうすれば情報を保存できますか? フラグメント クラスのメソッドが必要であり、コンストラクターの代わりにnewInstanceホスティング アクティビティを呼び出す必要があると思います。newInstanceしかし、私はそれを実装する方法がわかりません。どんな助けでも感謝します。ありがとう!

SingleFragmentActivity:

public abstract class SingleFragmentActivity extends FragmentActivity
{
    protected abstract Fragment createFragment();

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (fragment == null)
        {
            fragment = createFragment();
            fm.beginTransaction()
                .add(R.id.fragmentContainer, fragment)
                .commit();
        }
    }
}

ホスティング アクティビティ AdviceActivity からの関連コード:

public class AdviceActivity extends SingleFragmentActivity
{
    @Override
    protected Fragment createFragment()
    {
        return new AdviceFragment();
    }
}

ホスティング フラグメント AdviceFragment からの関連コード:

private boolean isTextButtonFirstClick = true;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    mTextButton = (Button) v.findViewById(R.id.textButton);
    mTextButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isTextButtonFirstClick)
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
                isTextButtonFirstClick = false;
            }
            else
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
            }
        }
    });
...
}

DialogFragment InputTextFragment からの関連コード:

public static InputTextFragment newInstance(String text, boolean isTextButtonFirstClick)
{
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_TEXTBUTTON_FIRSTCLICK, isTextButtonFirstClick);
    args.putSerializable(EXTRA_TEXT, text);

    InputTextFragment fragment = new InputTextFragment();
    fragment.setArguments(args);

    return fragment;
}

...

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    ...

    boolean isTextButtonFirstClick = getArguments().getBoolean(EXTRA_TEXTBUTTON_FIRSTCLICK);

    final EditText editText = (EditText) v.findViewById(R.id.dialogInputEditText);
    if (!isTextButtonFirstClick)
    {
        editText.setText(text);
        editText.setSelection(text.length());
    }

    ...
}

XML activity_fragment:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</RelativeLayout>
4

1 に答える 1

1

ブール値の isTextButtonFirstClick が誤って false に設定されているように聞こえます。

これは、ナビゲーション中に Advice Fragment の新しいインスタンスが作成されることを意味します。

試す

  • ブール値を保持するために、Advice Fragment の onCreate で setRetainInstance(true) を設定します。

  • R.id.fragmentContainer が XML のフラグメント タグである場合は、それを LinearLayout または RelativeLayout に変更します (とにかく上にフラグメントを追加していて、findFragmentById が常に null を返すと思われます)。

  • アクティビティのコードを次のように変更します。

    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fm.findFragmentByTag("singleFragment");
    
    if (fragment == null)
    {
        fragment = createFragment();
    }
    
       fm.beginTransaction()
            .replace(R.id.fragmentContainer, fragment,  "singleFragment" )
            .commit();
    

通常、プログラムでフラグメントを追加する場合はタグを使用しますが、XML でフラグメントを定義して Android フレームワークにライフサイクルを処理させる場合は、ID で見つけることができます。

中間のソリューションにいるように見え、両方を実行しようとしていますが、意図したとおりに機能しません。

フォーマットの問題がある場合は、これが役立つことを願っています。答えは電話から書かれています:-)

編集:

単純なタイプの情報 (ブール値など) のみを保存したい場合は、ここで私の古い回答の 1 つを示します:画面を回転するときにテキストビューをフラグメントに保存する

あなたの最後のコメントは、保持したい複雑な情報 (テキスト、写真、ビデオなど) を持っていることを明らかにしました。

すべてを Parcelable にするのは非常に面倒なので、2 つ目のアドバイスを次に示します。

  1. プロジェクトに EventBus を追加しますhttps://github.com/greenrobot/EventBus
  2. 次のような情報のホルダー クラスを作成します。

    public class AdviceHolder {
        private boolean isTextButtonFirstClick;
        private String text;
        private BitMap image;
        ... 
    
       // setter and getter methods (if using eclipse alt+shit+s 'create setter and getters from fields') 
    }
    
  3. AdviceActivity を開始するときに、新しい AdviceHolder を準備します。

    public class AdviceActivity extends SingleFragmentActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // make a new AdviceHolder if none existed
            AdviceHolder holder = new AdviceHolder();
            AdviceHolder existingHolder = EventBus.getDefault().getStickyEvent(AdviceHolder.class);
            if (existingHolder == null) {        
                 EventBus.getDefault().postSticky(holder);
            }
    
            super.onCreate(savedInstanceState);
        }
    
        @Override
        protected Fragment createFragment()
        {
            return new AdviceFragment();
        }
    }
    

この手順により、コード内のどこでもAdviceHolder オブジェクトを使用できるようになります。グローバルリポジトリと考えてください。

これは、アクティビティまたはフラグメント間をどのように移動しても、すべてが AdviceHolder にアクセスして編集できることを意味します。

たとえば、AdviceFragment では次のようになります。

private AdviceHolder holder;

...
@Override
public void onCreate (Bundle savedInstanceState) {
    AdviceHolder holder = (AdviceHolder)EventBus.getDefault().getStickyEvent(AdviceHolder.class);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    // read isTextButtonFirstClick from holder
    boolean isTextButtonFirstClick = holder.isTextButtonFirstClick();

    mTextButton = (Button) v.findViewById(R.id.textButton);
    mTextButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isTextButtonFirstClick)
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);

                // update isTextButtonFirstClick in holder
                holder.setTextButtonFirstClick(false);
                EventBus.getDefault().postStickyEvent(holder);
            }
            else
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
            }
        }
    });
...
}

ある時点で への入力が完了したらAdviceHolder(そしてそれをサーバーまたは計画に送信した後)、それを EventBus から削除して、 で新しいホルダーを作成できるようにしAdviceActivityます。

EventBus.getDefault().removeStickyEvent(AdviceHolder.class);

EventBus に関する他の例については、http: //www.stevenmarkford.com/passing-objects-between-android-activities/ をご覧ください。

これはすべて多くの情報です。あまり混乱しないことを願っています。

于 2014-10-02T01:31:54.107 に答える