質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

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

Android

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

2回答

2081閲覧

【Android Studio】あるFragmentから別のFragmentに値を渡す方法

y_itsuki

総合スコア7

Java

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

Android

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

1クリップ

投稿2018/02/21 17:15

前提・実現したいこと

Android Studioおよびjavaを扱うのは初めてで、
webで調べながら見よう見まねで作成しているような状況ですが、
あるFragmentから別のFragmentに値を渡す方法がわからず苦戦しております。
理解が足りていないことは重々承知で、お見苦しいかとは思いますが
ご教示いただけますと幸いです。

FragmentとViewPagerでTabLayoutを作っています。
各Tabの表示内容を別々のFragmentで表示します。

処理の流れは、
・Fragment2(=Tab2)に配置したspinnerで入力内容を選択し
・Fragment2のボタンを押すと、選択したspinnerの内容が
Fragment1(=Tab1)に配置したTableLayoutに書き込まれる。

Fragment2で入力、Fragment1で表示というイメージです。
※本来はfragment1でもう一段回処理して、最終的な履歴をFragment3(Tab3)に
書き込む予定なのですが、今回は割愛します。
フラグメントマネージャーにはFragmentが3つありますが気にしないでください。

発生している問題・エラーメッセージ

自分で調べた範囲では、bundleを介して値を渡せるということは分かったのですが、
実際にやってみるとnullになってしまいます。

該当のソースコード

【MainActivity.java】 package com.example.MyApp; import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // スライド用の部品 ViewPager viewPager = findViewById(R.id.viewpager); viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager(), MainActivity.this)); // 上部にタブをセットする TabLayout tabLayout = findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); } }
【SampleFragmentPagerAdapter.java】 package com.example.MyApp; import android.content.Context; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; public class SampleFragmentPagerAdapter extends FragmentPagerAdapter { final int PAGE_COUNT = 3; // Tabのタイトルテキスト。サイズやカラーはstyles.xmlで設定する。 private String tabTitles[] = new String[]{"現在の状況", "予約フォーム"}; private Context context; public SampleFragmentPagerAdapter(FragmentManager fm, Context context) { super(fm); this.context = context; } @Override public int getCount() { return PAGE_COUNT; } @Override public Fragment getItem(int position) { // fragmentを切り替える switch(position){ case 0: return new PageFragment(); case 1: return new PageFragment2(); case 2: return new PageFragment3(); } return null; } @Override public CharSequence getPageTitle(int position) { // Generate title based on item position return tabTitles[position]; }
【PageFragment2.java】 // 入力フォームを表示するTab2 package com.example.MyApp; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.Button; //Fragmentクラスを継承します public class PageFragment2 extends Fragment { // Fragmentで表示するViewを作成 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); // 画面回転時にFragmentの再生成を禁止 setRetainInstance(true); // fragment_page2.xmlのレイアウトをViewとして作成します。 // fragment_page2.xmlにはspinnerがいくつか並んでいて、 // 最下部にボタンが配置されている。 return inflater.inflate(R.layout.fragment_page2, container, false); } // Viewが生成し終わった時に呼ばれるメソッド @Override public void onViewCreated(View view, Bundle saveInstanceState){ super.onViewCreated(view, saveInstanceState); // 名前選択用のspinner設定 final Spinner spinnerName = view.findViewById(R.id.spinner_name); // spinnerの文字サイズなど変更できるように ArrayAdapter<String> adapterName = new ArrayAdapter<>(getContext(), R.layout.spinner_item, getResources().getStringArray(R.array.spinner_names)); // ドロップダウンメニューにするため adapterName.setDropDownViewResource(R.layout.spinner_dropdown_item); // spinner に adapterをセット spinnerName.setAdapter(adapterName); // (中略。上記のようなspinnerを複数設定) //ボタンを押したときのリスナーを設定 Button button01 = view.findViewById(R.id.button01); button01.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view){ // spinnerの選択内容をフラグメント1に渡すためにBundleにセット FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); PageFragment fragment = new PageFragment(); Bundle args = new Bundle(); args.putString("name_spinner", (String) spinnerName.getSelectedItem()); fragment.setArguments(args); fragmentTransaction.commit(); // spinnerを初期化 spinnerName.setSelection(0); // (中略。他のspinnerについても同様に設定) } }); } }
【PageFragment.java】 // 入力結果を表示するためのTab1 package com.example.MyApp; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.os.Bundle; //Fragmentクラスを継承します public class PageFragment extends Fragment { //Fragmentで表示するViewを作成 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); // 画面回転時にFragmentの再生成を禁止 setRetainInstance(true); //fragment_page.xmlのレイアウトをViewとして作成します。 // fragment_page.xmlにはTableLayoutとボタンが配置されています。 return inflater.inflate(R.layout.fragment_page, container, false); } // Viewが生成し終わった時に呼ばれるメソッド @Override public void onViewCreated(View view, Bundle saveInstanceState) { super.onViewCreated(view, saveInstanceState); final TextView name = view.findViewById(R.id.reserve_2c); // R.id.reserve_2c は Tbaleのセルのidです。 // ボタンを押したらBundleから値を受け取り、セルに書き込む。 // ※ 本当は、PageFragment2.javaでボタンを押した時点でセルへの書き込みまで // おこなうとか、ページがTab2からTab1に切り替わったことを検出して // セルに書き込む、とかにしたかったが、よく理解できなかったので // まずはボタンのOnClickListenerで動かしてみる。 Button button = view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // nullチェック Bundle bundle = getArguments(); if (bundle == null) { name.setText("null"); } else { // nullでなければspinnerで選択した内容をセルに書き込む name.setText(bundle.getString("name_spinner")); } // (中略。その他のspinnerについても同様に値を受け取りセルに書き込みたい) } }); } }

【PageFragment.java】でBundleから値を受け取れたかどうかをnullチェックすると、
nullが返って来て上手く値を受け渡しできずに困っています。

試したこと

Bundleにセットする時点で問題があるのかを確認するため、
【PageFragment2.java】にて、

final TextView testText = view.findViewById(R.id.test_text); testText.setText(args.getString("name_spinner"));

を加えてみると、spinnerNameで選択した内容がTextViewで表示されました。

しかし、同じ【PageFragment2.java】でも、

final TextView testText = view.findViewById(R.id.test_text); Bundle bundle = getArguments(); testText.setText(bundle.getString("name_spinner"));

とするとnullになります。

(これはbundleへのセットは行えているがゲットが上手く
できていないということでしょうか?)

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

Android Studio 3.0

以上、よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

FragmentTransactionのaddやreplace等のメソッドでフラグメントを配置しないと意味がありません。
また、この方法で実装した場合、画面に表示されているフラグメントインスタンスとは別のインスタンスにデータを渡すことになることは理解していますか?

データはFragment→Activity→Fragmentの流れで渡しましょう。

投稿2018/02/22 00:56

yona

総合スコア18155

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

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

y_itsuki

2018/02/22 22:47 編集

ご回答くださり、ありがとうございます。 addやreplaceを使うというのは、下記の様に理解したのですが、いかがでしょうか。 ・メインのレイアウトでフラグメントを配置する場所だけ確保しておき、  その場所のidをaddやreplaceに渡して対象のフラグメントを配置(置き換え)。 ・配置されたフラグメント側でbundleから値を受け取って何らかの処理を実行。 → この場合、今回私の作成したものはメインのレイアウトにはTabLayoutとViewPagerしか  配置されておりません。  FragmentPagerAdapterでポジションを検出し、対応するフラグメントを表示しているだけ  ですので、そもそもaddやreplaceする場所がなく、この方法は向いていないのでは、  と思い始めました。 >また、この方法で実装した場合、画面に表示されているフラグメントインスタンスとは別の >インスタンスにデータを渡すことになることは理解していますか? →よくわかっていなかったのですが、今私がやっていることは、画面に存在していないインスタンスに  値を渡そうとしている(もしくは新たに生成している?)にもかかわらず、そのインスタンスが  もとから存在しているかのように扱おうとしているからnullになるということでしょうか?
yona

2018/02/23 00:47

> この方法は向いていないのでは、と思い始めました。 その通りです。Fragmentにデータを渡す方法はたくさんありますが、それらは状況によって使い分ける必要があります。ネットで見つけた最初の方法に飛びついたらだめですよ。 あなたの採用しようとした方法はFragmentを初回配置する場合に使用する方法です。 また、インスタンスが違うというのはViewPagerAdapterが作ったフラグメントとあなたが作ったフラグメントは同じクラスから作り出した別のインスタンスです。 そのため、下記の状況になっています。 ・画面に配置されたフラグメントインスタンス ・新しく作った値を持つフラグメントインスタンス
y_itsuki

2018/02/26 15:02

お礼が遅くなり申し訳ありません。 今回は方針が間違っていたということで、色々ヒントを下さりありがとうございます。 まだ実現したいこと自体は解決していませんが、フラグメントの扱い方自体がよく分かって いなかったので、勉強しなおそうと思います。 今回はご回答、ありがとうございました。
guest

0

間が空きましたが、自己解決しました。
備忘録 兼 同じことで悩んでいる人に少しでも参考になればと思い、
ここに書いておこうと思います。

処理内容は、
フラグメント2にあるspinner(ここではspinnerName)を選択したあと、ボタンを押すと
選択内容をフラグメント1のTableLayout内のセル(ここではreserve_2c)に書き込む
というものです。

【PageFragment2.java】 //Fragmentクラスを継承します public class PageFragment2 extends Fragment { // 中略 最初のコードから変更なし // Viewが生成し終わった時に呼ばれるメソッド @Override public void onViewCreated(View view, Bundle saveInstanceState){ super.onViewCreated(view, saveInstanceState); // 中略 spinnerの処理部分は最初のコードから変更なし     final TextView reserve_2c_text = getActivity().findViewById(R.id.reserve_2c); // R.id.reserve_2cはフラグメント1内の書き込みたいセルのid     Button button01 = view.findViewById(R.id.button01); // button01を押したとき button01.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view){ // ここでフラグメント1にあるテーブル内のセルに値を書き込んでいる reserve_2c_text.setText((String) spinnerName.getSelectedItem()); } }); } }

ポイントは、getActivity()でフラグメントが属するアクティビティを取得している点です。
フラグメントは必ずアクティビティに属する形で使用されます。
今回のケースでは、フラグメント1とフラグメント2はどちらも同じアクティビティに属しています。
getActivity()メソッドで両フラグメントが所属するアクティビティを経由することで、
フラグメント2から直接フラグメント1内のidを参照することができるようになります。

※ちなみに
インターネットで「フラグメント 値 受け渡し」と検索すると出て来る情報の
多くが、Bundleにセットした値を受け取るというというものでしたが、
これはyona様のコメントにもある通り、フラグメントを初回配置する場合に使用する方法で、
今回私がやりたかったような既に生成した後のフラグメントに対して値を書き込む場合には
向いていないようです。個人的にはそれを理解するまでに時間がかかってしまいました。。。

以上です。

投稿2018/03/04 12:48

y_itsuki

総合スコア7

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問