249

リストから項目を選択する、テキストを入力するなど、さまざまな目的でDialogFragmentsを使用しています。

呼び出し元のアクティビティ/フラグメントに値 (つまり、文字列またはリストの項目) を返す最良の方法は何ですか?

現在、呼び出しアクティビティを実装DismissListenerし、DialogFragment にアクティビティへの参照を与えています。次に、DialogOnDimissはアクティビティ内のメソッドを呼び出し、Activity は DialogFragment オブジェクトから結果を取得します。非常に面倒で、DialogFragment がアクティビティへの参照を失うため、構成の変更 (方向の変更) では機能しません。

助けてくれてありがとう。

4

15 に答える 15

259

myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)ダイアログを表示する場所から使用し、ダイアログが終了したら、そこから を呼び出して、それを含むフラグメントにgetTargetFragment().onActivityResult(getTargetRequestCode(), ...)実装できます。onActivityResult()

onActivityResult()特にアクティビティがまったく含まれていないため、の乱用のように思えます。しかし、私はそれが公式のGoogleの人々によって推奨されているのを見てきました.APIデモでもそうかもしれません. g/setTargetFragment()追加されたものだと思います。

于 2012-11-17T19:01:40.653 に答える
143

ここでわかるように、それを行うための非常に簡単な方法があります。

DialogFragment次のようなインターフェイスリスナーを追加します。

public interface EditNameDialogListener {
    void onFinishEditDialog(String inputText);
}

次に、そのリスナーへの参照を追加します。

private EditNameDialogListener listener;

これは、リスナー メソッドを「アクティブ化」するために使用され、親アクティビティ/フラグメントがこのインターフェイスを実装しているかどうかを確認するためにも使用されます (以下を参照)。

Activity/ FragmentActivity/Fragmentその「呼び出し」では、このインターフェイスを実装するだけDialogFragmentです。

を閉じて結果を返しDialogFragmentたい場所に追加する必要があるのは、次のとおりです。DialogFragment

listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();

mEditText.getText().toString()呼び出し元に返されるものはどこにありますかActivity

他の何かを返したい場合は、リスナーが受け取る引数を変更するだけであることに注意してください。

最後に、インターフェイスが実際に親アクティビティ/フラグメントによって実装されているかどうかを確認する必要があります。

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    // Verify that the host activity implements the callback interface
    try {
        // Instantiate the EditNameDialogListener so we can send events to the host
        listener = (EditNameDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement EditNameDialogListener");
    }
}

この手法は非常に柔軟で、まだダイアログを閉じたくない場合でも結果をコールバックできます。

于 2013-02-11T08:34:09.050 に答える
22

答えを出すには遅すぎるかもしれませんが、 から結果を取得するために私がしたことは次のとおりDialogFragmentです。@brandonの答えに非常に似ています。ここでDialogFragmentは、フラグメントから呼び出しています。このコードを、ダイアログを呼び出している場所に配置してください。

FragmentManager fragmentManager = getFragmentManager();
            categoryDialog.setTargetFragment(this,1);
            categoryDialog.show(fragmentManager, "dialog");

categoryDialogDialogFragmentが呼び出したい場所はどこで、この後dialogfragment、データを意図的に設定している場所にこのコードを配置します。の値resultCodeは 1 で、設定するか、システム定義を使用できます。

            Intent intent = new Intent();
            intent.putExtra("listdata", stringData);
            getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
            getDialog().dismiss();

ここで、呼び出し元のフラグメントに戻り、このメソッドを実装します。必要に応じて、if 条件でデータの有効性または結果の成功を確認しresultCodeますrequestCode

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);        
        //do what ever you want here, and get the result from intent like below
        String myData = data.getStringExtra("listdata");
Toast.makeText(getActivity(),data.getStringExtra("listdata"),Toast.LENGTH_SHORT).show();
    }
于 2016-04-09T08:25:29.733 に答える
11

FragmentがそのActivityまで通信できるようにするための別のアプローチ:

1)フラグメントでパブリック インターフェイスを定義し、その変数を作成します。

public OnFragmentInteractionListener mCallback;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(int id);
}

2)アクティビティをフラグメントの mCallback 変数にキャストする

try {
    mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
    Log.d(TAG, e.getMessage());
}

3)アクティビティにリスナーを実装する

public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
     //your code here
}

4)アクティビティで OnFragmentInteraction をオーバーライドする

@Override
public void onFragmentInteraction(int id) {
    Log.d(TAG, "received from fragment: " + id);
}

詳細情報: https://developer.android.com/training/basics/fragments/communicating.html

于 2017-07-30T19:00:39.257 に答える
10

私が見つけた簡単な方法の 1 つは次のとおりです。

  CallingActivity callingActivity = (CallingActivity) getActivity();
  callingActivity.onUserSelectValue("insert selected value here");
  dismiss();

次に、Dialog Fragment を呼び出したアクティビティで、適切な関数を次のように作成します。

 public void onUserSelectValue(String selectedValue) {

        // TODO add your implementation.
      Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
    }

トーストは、それが機能することを示すことです。私のために働いた。

于 2015-12-23T22:44:43.653 に答える
7

DialogFragmentローカル ブロードキャストをActivityコミュニケーションに使用することを誰も提案していないことに非常に驚いています。他の提案よりもはるかにシンプルでクリーンだと思います。基本的にActivity、ブロードキャストをリッスンするように登録し、インスタンスからローカル ブロードキャストを送信しDialogFragmentます。単純。すべてを設定する方法の詳細なガイドについては、こちらを参照してください。

于 2015-10-04T18:20:48.957 に答える
4

または、ここに示すように ViewModel を共有します。

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

https://developer.android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments

于 2018-10-29T15:00:04.620 に答える
-3

オプションの 1 つとして (まだ誰も言及していないため)、Otto のようなイベント バスを使用できます。したがって、ダイアログで次のことを行います。

bus.post(new AnswerAvailableEvent(42));

そして、呼び出し元 (アクティビティまたはフラグメント) にサブスクライブさせます。

@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
   // TODO: React to the event somehow!
}
于 2017-09-20T16:18:36.923 に答える