🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

7182閲覧

android:子フラグメントから親フラグメントに値を渡したい

mimon

総合スコア15

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2019/09/10 08:06

前提・実現したいこと

タイトル通り、AフラグメントからBフラグメントに遷移時、Bフラグメントで入力した値をAフラグメントに渡す方法がわかりません。

具体的には、
・日付を表示しているAフラグメントで、日付をクリック
・カレンダービューが貼ってあるBフラグメントを表示
・カレンダーで日付を選択時にBフラグメントを閉じて選択した日付をAフラグメントに表示

以上になります。

フラグメントの遷移はナビゲーションエディタでNavHostFragmentを使用して行っています。
Aフラグメント表示時には初期表示の日付をSafeArgsで受け取っています。
Bフラグメントの非表示はpopBackStack()でひとつ前(Aフラグメント)に戻っています。

簡単なサンプルを載せておきます。
※Aフラグメントは別のフラグメントから呼び出しています。
※onCreateView部分は省略しています。

AFragment.tk

kotlin

1class AFragment: Fragment() { 2val args: AFragmentArgs by navArgs() 3 4override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 5 super.onViewCreated(view, savedInstanceState) 6 // 初期表示用日付 7 val date:String = args.showDate 8 9 if(date:String == "") 10 // 当日を表示 11     else 12 // パラメタの日付を表示 13      //***********************************************      14 // ここでパラメタではなく、Bで選択時はBの日付をセットしたい!! 15      // Bからargs.showDateを書き換えられる? 16      // または別のパラメタを渡せる? 17 //*********************************************** 18      textDate.text = date 19 20     // 日付クリック時 21     textDate.setOnClickListener { 22    // Bフラグメントを表示 23    val action = AFragmentDirections.actionAFragmentToBFragment() 24 Navigation.findNavController(view as View).navigate(action) 25 } 26}

BFragment.tk

kotlin

1class BFragment: Fragment() { 2 3 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 4 super.onViewCreated(view, savedInstanceState) 5 6 calendarView.setOnDateChangeListener { view, year, month, dayOfMonth -> 7 // カレンダーの選択日付をセット 8 val setDate = year.toString() + java.lang.String.format("%0${2}d", 9 month + 1) + java.lang.String.format("%0${2}d", dayOfMonth) 10         11 //***********************************************  12 // ここで、Aフラグメントになんとかして値を渡したい!! 13 //***********************************************        14       15 // Aフラグメントに戻る 16 FragmentManager?.popBackStack() 17    } 18}

試したこと

単純に、BからAに直接セットできないかと、popBackStackする前に
activity?.textDate?.setText(setDate) なんてしてみました。もちろん空でしたが。
popBackStackでは前のFragmentの情報はセットされたままですので、選択した日付だけ更新して表示したいです。
今回はカレンダービューを使用していますが、例えばBで入力した値をAに表示する単純な動きを実装したいだけなのです。
Fragmentの初期表示時にパラメタを渡す方法はわかるのですが、ライフサイクルが終わるときに前のFragment(存在する場合ですが)に値を渡すことは可能でしょうか?
基本的なことですがよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Android Studio 3.4.1
SDK 29
kotlin

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Navigationコンポーネントをお使いなら、次の1,2の方法があります。

1. navigationリソースで「戻る」アクションを定義する

厳密にはpopBackStackで1つ戻る遷移ではなく、2つ戻って新しいFragmentを表示する動きになりますが、それっぽいアクションを定義することができます。app:popUpToInclusiveを付けるところがポイントです。

xml

1<action 2 android:id="@+id/action_B_to_A" 3 app:destination="@+id/a_fragment" 4 app:popUpTo="@+id/a_fragment" 5 app:popUpToInclusive="true" 6 />

プログラム側からは普通にSafeArgsを渡して上記の遷移の処理を呼べばOKです。

kotlin

1val action = BFragmentDirections.actionBToA(...) 2findNavController().navigate(action)

2.共有するViewModelを通してFragment間の通信を行う

単純な値の受け渡しなら1.の方法で済むと思いますが、ある程度やり取りが複雑になるようなら共有のViewModelを利用するのが現在Googleの推奨している方法です。ViewModelをすでに導入済み、もしくは導入に抵抗がないようでしたら後々便利なのでこの方法が良いかもしれません。

ドキュメント: https://developer.android.com/topic/libraries/architecture/viewmodel#sharing


3. setTargetFragment/getTargetFragmentでやり取り

Navigationコンポーネントの利用は諦めてFragment同士のやり取りを実装するなら、こちらの方法になると思います。

参考: https://tech.mokelab.com/android/Fragment/result.html

投稿2019/09/11 13:41

kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mimon

2019/09/12 05:08

いつも回答ありがとうございます! やはりNavigationでの実装で統一したく、1の方法で解決しました。 2についはいずれ必ず必要になると思いますので勉強します。 3については、以後必ずやこちらの方法で・・・ (s.m_1さんにせっかく教えていただいたのに、私の呼び方がバカでしたね) まだまだ基本編なので頑張ります。ありがとうございました!
guest

0

他に解決策はあるかもしれませんが、私なら interface を使うと思います。

Kotlin

1interface OnDateChangeListener { 2 fun onDateChange(渡したい値:) 3}

Kotlin

1class BFragment : Fragment() { 2 3 var listener: OnDateChangeListene? = null 4 5 calendarView.setOnDateChangeListener { view, year, month, dayOfMonth -> 6 // カレンダーの選択日付をセット 7 val setDate = year.toString() + java.lang.String.format("%0${2}d", 8 month + 1) + java.lang.String.format("%0${2}d", dayOfMonth) 9         10 //***********************************************  11 // ここで、Aフラグメントになんとかして値を渡したい!! 12 listener?.onDateChange(渡したい値)       13       14 // Aフラグメントに戻る 15 FragmentManager?.popBackStack() 16 } 17 18}

Kotlin

1class AFragment : Fragment(), OnDateChangeListener { 2 3 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 4 super.onViewCreated(view, savedInstanceState) 5 // BFragment のインスタンス生成 6 bFragment = *** 7 bFragment.listener = this 8 } 9 10 override fun onDateChange(渡したい値:) { 11 // BFragment で設定された日付を取得 12 } 13 14}

投稿2019/09/11 01:10

s.m_1

総合スコア293

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mimon

2019/09/11 05:59

回答ありがとうございます! 早速インターフェースを実装しようとやっていますが 現在まだコールバックメソッドに戻ってこない状態です。 BFragmentクラスの中に   interface OnDateChangeListener { fun onDateChange(date: Int) } を作成し、  var listener: OnDateChangeListene? = null calendarView.setOnDateChangeListenerの中に  listener?.onDateChange(setDate.toInt()) を追加しました。 AFragmentでは BFragment.OnDateChangeListener を継承し、onDateChangeを実装しました。 ただ、回答にありました、  // BFragment のインスタンス生成 bFragment = *** bFragment.listener = this この部分でつまってます。(基本的なことですいません・・・) 今回はBFragmentへの遷移はナビゲーションを使用しており、特にインスタンを作成していません。 (AFragment.tkの一番下の部分です) リスナーを設定する場合は、ナビゲーションは使用できないでしょうか・・・?
s.m_1

2019/09/11 06:26

でしたら、supportFragmentManager.findFragmentById() で fragment を取得できませんか?
mimon

2019/09/11 08:00

どうにもうまく取得できず、結局この部分のみナビゲーションでの遷移を諦め fragmentManagerを使用して addToBackStack(null) replace(id.XX, bFragment) commit() の流れで遷移させるとコールバックできました。 知識不足でせっかくのアドバイスを活かせませんでしたが、interfaceの実装を教えていただき大変助かりました。ありがとうございました!!
kakajika

2019/09/11 10:33

この方法だと画面回転等でFragmentが再生成された場合にコールバックが解除されてしまって良くないです。せめてsetTargetFragment/getTargetFragmentでやり取りするようにするべきです。
mimon

2019/09/12 02:19

>kakajikaさん はっ!そうなのですねっ!? 本編の回答もありがとうございます。 まだまだ基本編の状態で大変お恥ずかしいですが、 すぐにまずは1の方法を試してみます。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問