web-dev-qa-db-ja.com

DialogFragmentから結果を受け取る

私はDialogFragmentsを使用しています。リストから項目を選択し、テキストを入力します。

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

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

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

221
James Cross

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

特にアクティビティをまったく伴わないため、onActivityResult()の不正使用のようです。しかし、私は公式のグーグルの人々、そしておそらくAPIデモでも推奨されているのを見ました。 g/setTargetFragment()が追加された理由だと思います。

237
Timmmm

here を見るとわかるように、非常に簡単な方法があります。

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

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

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

private EditNameDialogListener listener;

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

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");
    }
}

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

131
Assaf Gamliel

DialogFragmentから結果を受け取るはるかに簡単な方法があります。

まず、Activity、Fragment、またはFragmentActivityで、次の情報を追加する必要があります。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Stuff to do, dependent on requestCode and resultCode
    if(requestCode == 1) { // 1 is an arbitrary number, can be any int
         // This is the return result of your DialogFragment
         if(resultCode == 1) { // 1 is an arbitrary number, can be any int
              // Now do what you need to do after the dialog dismisses.
         }
     }
}

requestCodeは基本的に、呼び出したDialogFragmentのintラベルです。これがどのように機能するかをすぐに示します。 resultCodeは、DialogFragmentから送り返され、現在待機中のActivity、Fragment、またはFragmentActivityに何が起こったかを伝えるコードです。

次に進むコードは、DialogFragmentの呼び出しです。例は次のとおりです。

DialogFragment dialogFrag = new MyDialogFragment();
// This is the requestCode that you are sending.
dialogFrag.setTargetFragment(this, 1);     
// This is the tag, "dialog" being sent.
dialogFrag.show(getFragmentManager(), "dialog");

これらの3行を使用して、DialogFragmentを宣言し、requestCode(onActivityResult(...)を呼び出すとダイアログが閉じられ、ダイアログが表示されます)を設定します。それは簡単です。

ここで、DialogFragmentでdismiss()の直前に1行追加するだけで、onActivityResult()にresultCodeを送り返すことができます。

getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();

それでおしまい。なお、resultCodeはint resultCodeとして定義されており、この場合はresultCode = 1;に設定しています。

これで、DialogFragmentの結果を呼び出し側のActivity、Fragment、またはFragmentActivityに返送できるようになりました。

また、この情報は以前に投稿されたように見えますが、十分な例が示されていなかったため、詳細を提供すると思いました。

EDIT 06.24.2016上記の誤解を招くコードをおaび申し上げます。しかし、次のように見えるアクティビティに結果を戻すことはできません。

dialogFrag.setTargetFragment(this, 1);

Fragmentではなく、ターゲットActivityを設定します。したがって、これを行うには、InterfaceCommunicatorの実装を使用する必要があります。

DialogFragmentにグローバル変数を設定します

public InterfaceCommunicator interfaceCommunicator;

パブリック関数を作成して処理します

public interface InterfaceCommunicator {
    void sendRequestCode(int code);
}

次に、Activityの実行が完了したときにコードをDialogFragmentに送り返す準備ができたら、単にdismiss();DialogFragmentの前に追加します。

interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.

アクティビティでは、次の2つのことを行う必要があります。1つ目は、適用されなくなった1行のコードを削除することです。

dialogFrag.setTargetFragment(this, 1);  

その後、インターフェースを実装すれば完了です。クラスの最上部にあるimplements句に次の行を追加することにより、これを行うことができます。

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

そして、@Overrideアクティビティ内の関数、

@Override
public void sendRequestCode(int code) {
    // your code here
}

このインターフェイスメソッドは、onActivityResult()メソッドと同じように使用します。インターフェイスメソッドがDialogFragments用であり、もう1つがFragments用である場合を除きます。

46
Brandon

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

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

ここでcategoryDialogは呼び出したいDialogFragmentであり、この後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();
    }
20
vikas kumar

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

9
lcompare

私が見つけた簡単な方法の1つは次のとおりです。これを実装するのは、dialogFragmentです。

  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();
    }

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

8
ZeWolfe15

DialogFragmentからActivityへの通信にローカルブロードキャストを使用することを誰も提案していないことに非常に驚いています!私はそれが他の提案よりもはるかにシンプルでクリーンであることがわかりました。基本的に、Activityを登録してブロードキャストをリッスンし、DialogFragmentインスタンスからローカルブロードキャストを送信します。シンプル。すべての設定方法に関するステップバイステップガイドについては、 here を参照してください。

6
Adil Hussain

または、次のように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

1
Malachiasz

私の場合、targetFragmentに引数を渡す必要がありました。しかし、「Fragment already active」という例外が発生しました。だから、parentFragmentが実装するDialogFragmentでInterfaceを宣言しました。 parentFragmentがDialogFragmentを開始すると、自身をTargetFragmentとして設定します。次に、DialogFragmentで呼び出しました

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);
1
Lanitka

引数を送信し、2番目のフラグメントから結果を受信する場合、Fragment.setArgumentsを使用してこのタスクを実行できます。

static class FirstFragment extends Fragment {
    final Handler mUIHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case 101: // receive the result from SecondFragment
                Object result = msg.obj;
                // do something according to the result
                break;
            }
        };
    };

    void onStartSecondFragments() {
        Message msg = Message.obtain(mUIHandler, 101, 102, 103, new Object()); // replace Object with a Parcelable if you want to across Save/Restore
                                                                               // instance
        putParcelable(new SecondFragment(), msg).show(getFragmentManager().beginTransaction(), null);
    }
}

static class SecondFragment extends DialogFragment {
    Message mMsg; // arguments from the caller/FirstFragment

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onViewCreated(view, savedInstanceState);
        mMsg = getParcelable(this);
    }

    void onClickOK() {
        mMsg.obj = new Object(); // send the result to the caller/FirstFragment
        mMsg.sendToTarget();
    }
}

static <T extends Fragment> T putParcelable(T f, Parcelable arg) {
    if (f.getArguments() == null) {
        f.setArguments(new Bundle());
    }
    f.getArguments().putParcelable("extra_args", arg);
    return f;
}
static <T extends Parcelable> T getParcelable(Fragment f) {
    return f.getArguments().getParcelable("extra_args");
}
0
Yessy

コトリンで

// My DialogFragment

クラスFiltroDialogFragment:DialogFragment()、View.OnClickListener {

var listener: InterfaceCommunicator? = null

override fun onAttach(context: Context?) {
    super.onAttach(context)
    listener = context as InterfaceCommunicator
}

interface InterfaceCommunicator {
    fun sendRequest(value: String)
}   

override fun onClick(v: View) {
    when (v.id) {
        R.id.buttonOk -> {    
    //You can change value             
            listener?.sendRequest('send data')
            dismiss()
        }

    }
}

}

//私の活動

クラスMyActivity:AppCompatActivity()、FiltroDialogFragment.InterfaceCommunicator {

override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}

}

私はそれが役立つことを願っています、あなたが改善できるならそれを編集してください。私の英語はあまり上手ではありません

0
Irvin Joao