web-dev-qa-db-ja.com

ボトムシートダイアログフラグメントから値を取得する

フラグメントAからbottomSheetDialogFragmentを開始しています。そのbottomSheetDialogFragmentから日付を選択して、フラグメントAに設定します。

選択日付はすでに完了しています。フラグメントAで取得して、いくつかのフィールドに設定したいだけです。

どうすれば値を取得できますか?それを行う方法の提案はありますか?

10
Abdulrahman

このようなインターフェースクラスを作成します

public interface CustomInterface {

    public void callbackMethod(String date);
}

このインターフェイスをActivityまたはFragmentに実装します。このインターフェイスのオブジェクトを作成します。

private CustomInterface callback;

onCreateまたはonCreateViewで初期化します

callback=this;

次に、このコールバックを呼び出すときにBottomSheetDialogFragmentコンストラクターに渡します。

yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");

今あなたのBottomSheetFragmentのコンストラクタで

プライベートCustomInterfaceコールバック。

public SelectStartTimeSheet(CustomInterface callback){

this.callback=callback;

}

最後に、このコールバックオブジェクトを使用して日付を設定します

callback.callbackMethod("your date");

この日付は、フラグメントまたはcallbackMethod関数のアクティビティで受け取ります。

12
AbhayBohra

ドキュメントが言っているように、フラグメントのコンストラクタをオーバーライドすることは悪い習慣です:

Everyフラグメントには*空のコンストラクターが必要なので、アクティビティの状態を復元するときにインスタンス化できます。

コールバックをパラメーターとして渡す別のコンストラクターを使用している場合、フラグメントがフレームワークによって再ソートされると、アプリがクラッシュします

推奨される方法は、viewModelとlivedataを使用することです。

2
hglf

あなたは以下のようにdoを使うことができます:

アカウントフラグメントコードを選択


class SelectAccountFragment(val clickListener: OnOptionCLickListener) : BottomSheetDialogFragment() {


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bottom_fragment_accounts, container, false)
    }



    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val list = DataProcessorApp(context).allUsers

        val rvAccounts = view.findViewById<RecyclerView>(R.id.rvAccounts)

        rvAccounts.layoutManager = LinearLayoutManager(context)
        rvAccounts.adapter = AccountsAdapter(context, list)

        Log.e(tag,"Accounts "+list.size);

        tvAccountAdd.setOnClickListener {
            val intent = Intent(context,LoginActivity::class.Java)
            startActivity(intent)
        }

        tvManageAccounts.setOnClickListener {
            Log.e(tag,"Manage Click")
            clickListener.onManageClick()
        }
    }


    interface OnOptionCLickListener{
        fun onManageClick()
    }

}


次に、以下のように別のフラグメント/アクティビティを表示してコールバックします

 SelectAccountFragment accountFragment = new SelectAccountFragment(() -> {

          //get fragment by tag and dismiss it

          BottomSheetDialogFragment fragment = (BottomSheetDialogFragment) getChildFragmentManager().findFragmentByTag(SelectAccountFragment.class.getSimpleName();
          if (fragment!=null){
               fragment.dismiss();
          }

});

accountFragment.show(getChildFragmentManager(),SelectAccountFragment.class.getSimpleName());
1
imran khan

BottomSheetDialogFragmentを使用している場合、これはフラグメントであるため、インターフェースを作成し、フラグメントのonAttachライフサイクルメソッドでバインドし、リスナー/コールバックタイプへのアクティビティ参照の適切なキャストを実行する必要があります。

このインターフェイスをアクティビティに実装し、フラグメントの内部のrecyclerviewのアイテムをクリックしたときに変更をディスパッチします。

これはよく知られているパターンであり、 here で詳しく説明されています

Androidコンポーネント間でプリミティブ/シンプル/小さなデータを常に渡すことにより、コンポーネントは必要な状態を取得できるため、アプリアーキテクチャを再考することが1つの大きなアドバイスです。後で依存関係。

たとえば、ビットマップ、データクラス、DTO、ビュー参照などの大きなオブジェクトを渡してはいけません。

  • 最初に、アプリの応答性に影響を与えるParcelに関するシリアル化プロセスが進行中です
  • 次に、 TransactionTooLarge タイプのエラーが発生する可能性があります。

お役に立てば幸いです。

1
william gouvea

LocalBroadcastManager を使用することもできます。そして、hglfが言ったように、インターフェイスのcallBack方法を引き続き使用する場合は、フラグメントの空のコンストラクターを保持し、代わりにnewInstance(Type value)を使用してフラグメントをインスタンス化することをお勧めします。

0
Abdelkader