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

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

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

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Android

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

Android Studio

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

Kotlin

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

Q&A

解決済

1回答

5651閲覧

AndroidのFragmentが重なって表示されてしまう

atRhod

総合スコア10

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Android

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

Android Studio

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

Kotlin

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

0グッド

1クリップ

投稿2020/09/21 06:32

編集2020/09/21 15:08

androidアプリのfragmentの表示でどうしても出来ないことがあり、質問させて頂きます。

#実現したいこと
現在作成しているアプリは画面下部にナビ、その上部にfragumentのListViewが表示されており、リストの項目をタップしていくことで次のfragmentを表示するアプリを作っております。fragmentは3階層まであり、3階層目でユーザーが選択した項目の詳細(用語説明など)を表示させるものです。
fragmentの書き換えには、replace(R.id.○○, 次のfragment)を用いております。

イメージ説明

問題点

しかし、リストに表示される項目をタップすると、次のフラグメントが重なって表示されてしまいます。

イメージ説明

また、Androidのバックキーを押すと、一つ前の階層のfragmentに戻って欲しいのですが、全て飛ばして最初の階層まで戻ってしまう状況です。

試したこと

調べていくと、「XML内に描いたfragmentはremove、replace」してはならない」という情報があった為、それを踏まえ以下のようにコードを書きました。仮となるFlameLayoutをXMLへ書いておき、onCreateで即座に最初のフラグメント「homeFragment」でreplaceしています。

XML

1<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:id="@+id/container" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent"> 7 8 <!-- 下部のナビの部分 --> 9 <com.google.android.material.bottomnavigation.BottomNavigationView 10 android:id="@+id/nav_view" 11 android:layout_width="0dp" 12 android:layout_height="wrap_content" 13 android:layout_marginStart="0dp" 14 android:layout_marginEnd="0dp" 15 android:background="?android:attr/windowBackground" 16 app:layout_constraintBottom_toBottomOf="parent" 17 app:layout_constraintLeft_toLeftOf="parent" 18 app:layout_constraintRight_toRightOf="parent" 19 app:menu="@menu/bottom_nav_menu" /> 20 21 22 <!-- このフレームレイアウトは仮。MainActivityのonCreateとともにホームフラグメントへ置き換えられる --> 23 <FrameLayout 24 android:id="@+id/nav_host" 25 android:layout_width="match_parent" 26 android:layout_height="match_parent" 27 app:layout_constraintHorizontal_bias="0.0" 28 app:layout_constraintLeft_toLeftOf="parent" 29 app:layout_constraintRight_toRightOf="parent" 30 android:layout_marginBottom="70dp" 31 > 32 </FrameLayout> 33</androidx.constraintlayout.widget.ConstraintLayout>

Kotlin

1class MainActivity : AppCompatActivity(){ 2 override fun onCreate(savedInstanceState: Bundle?) { 3 super.onCreate(savedInstanceState) 4 //メイン画面の読み込み 5 setContentView(R.layout.activity_main) 6 //ページ下部のナビ部分を読み込み 7 val navView: BottomNavigationView = findViewById(R.id.nav_view) 8 9 //FlameLayoutを即座に、最初のfragment「homeFragment」のリストで上書きする 10 var homeFragment: HomeFragment = HomeFragment() 11 val fragmentManager = supportFragmentManager 12 val transaction = fragmentManager.beginTransaction() 13 transaction.replace(R.id.nav_host, homeFragment) 14 transaction.commit() 15 } 16}

表示される最初のhomeFragmentは下記のように書きました。ListViewの項目がタップされたときのイベントリスナーの部分で次のfragmentである「caregory」フラグメントへreplaceしています。

Kotlin

1class HomeFragment : Fragment() { 2 override fun onCreateView( 3 inflater: LayoutInflater, 4 container: ViewGroup?, 5 savedInstanceState: Bundle? 6 ): View? { 7 val root = inflater.inflate(R.layout.list_view, container, false) 8 return root 9 } 10 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 11 super.onViewCreated(view, savedInstanceState) 12 // ListViewに表示するデータを読み込む 13 val homeArray = resources.getStringArray(R.array.home_array) 14 // ListViewをセット 15 val adapter = 16 this.context?.let { ArrayAdapter<String>( 17 it, 18 android.R.layout.simple_list_item_1, 19 homeArray 20 ) } 21 val listView: ListView = view.findViewById(R.id.listView) as ListView 22 listView.adapter = adapter 23 24 // listViewの行がクリックされた時のイベントリスナー 25 listView.setOnItemClickListener { parent, view, position, id -> 26 27 //次のフラグメント「カテゴリフラグメント」を表示する 28 val fragmentManager: FragmentManager = childFragmentManager 29 30 // FragmentManagerからFragmentTransactionを作成 31 val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() 32 33 //  次のリストとなるFragmentの作成 34 val categoryFragment: Fragment = CategoryFragment() 35 36 // 次のフラグメントへreplace 37 fragmentTransaction.replace(R.id.list, categoryFragment) 38 39 // backstackに追加 → 端末の戻るボタン押した時に、このアクティビティに戻ってくる設定にする 40 fragmentTransaction.addToBackStack(null) 41 42 // 上記の変更を反映する 43 fragmentTransaction.commit() 44 } 45 } 46}

また、HomeFragmentにて使用している「R.id.list」は以下のXMLファイル「list_view.xml」にて記述しております。

XML

1<androidx.constraintlayout.widget.ConstraintLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 android:id="@+id/list" 8 tools:context=".ui.home.HomeFragment"> 9 10 <ListView 11 android:id="@+id/listView" 12 android:layout_width="match_parent" 13 android:layout_height="match_parent" 14 android:layout_marginStart="8dp" 15 android:layout_marginTop="8dp" 16 android:layout_marginEnd="8dp" 17 > 18 </ListView> 19</androidx.constraintlayout.widget.ConstraintLayout>

なかなか先に進めておらず、ご教授いただければ幸いです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

ご提示いただいたソースファイルだけでは再現テストができないので、ソースファイルを眺めた範囲で気がついたことのみで。

MainActivityではnav_hostというIDのFrameLayoutにフラグメントを描画していますが、HomeFragmentではR.id.listというご提示のソースファイルでは出てこないIDに対してreplaceを行おうとされています。

これでは、nav_hostに描画されたフラグメントはそのまま維持されることになるので、それが二重に描画されているように見える原因ではないかと思えます。文字通りreplaceですから、R.id.nav_hostの中に現存するフラグメントを入れ替えればいいはずです。

また、このとき親のレイアウトに対して作業を行うことになるので、FragmentManagerをparentFragmentManagerで得なければならないのではないかと思います。

投稿2020/09/21 13:57

keicha_hrs

総合スコア6768

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

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

atRhod

2020/09/21 15:03

keicha_hrs様 いつもご回答を頂きありがとうございます。 (1)fragmentのIDに関して 「R.id.nav_host」と「R.id.list」の二つのidがあるから、その二つのIDが2重で表示されているという状況の可能性があるのですね。R.id.nav_hostの中に存在するフラグメントを差し替えるには、以下のコードだと考えましたが、どうもこのコードに書き換えるとクラッシュしてしまうので、書き方が違うようです… fragmentTransaction.replace(R.id.nav_view, categoryFragment) エラー内容: java.lang.IllegalArgumentException: No view found for id 0x7f090094 (com.example.electformula:id/nav_view) for fragment CategoryFragment{36d1ceb9 (fd4f3450-719d-40ba-8fec-35d284425a61) id=0x7f090094} CategoryFragmentによって置き換えられる「nav_view」がありません!という意味でしょうか。個人的には、nav_viewはreplaceによって無くなってしまった、と思ってます。それでhomeFragmentによって表示されるレイアウトである「R.id.list」を書いていました。また、質問には書いておらず申し訳ないのですが、「3回層目のフラグメント」も同様にR.id.listを置き換えているのですが、1、2階層目に加えてさらにレイアウトが重なる状況です。(何かヒントになれば幸いです。) 他のサイト様では、背景色を白にすることで対応してある記事もあるようですね。その方法も検討してみます。 (2)parentFragmentManagerに関して ・Activityからfragmentを呼び出す→supportFragmentManagerで得る ・fragmentからfragmentを呼び出す→childFragmentManagerで得る と考えていました。parentFragmentManagerというものもあるのですね。…調べてもなかなか情報に辿り着けず、もう少し探してみます。 また、再現テストに関して情報不足で申し訳ございません。R.id.listのコードを追記させて頂きます。
keicha_hrs

2020/09/22 07:23 編集

> (1)fragmentのIDに関して R.id.nav_viewではなく、R.id.nav_hostではありませんか・・・?(nav_viewはBottomNavigationViewのIDですよね)フラグメントを描画するFrameLayoutは「入れ物」と考えれば良いと思います。何かしらのフラグメントを描画しても無くなるわけではありません。「入れ物」の中身を取り替えるからreplaceなわけです。
keicha_hrs

2020/09/22 08:08

プロジェクト作成のときにBottom Navigation Activityを選択したのならば、resの下にnavigationというフォルダーがあるはずです。これはNavigationコンポーネントというAndroidの機能を利用するためのファイルが入ったもので、フラグメントの遷移を視覚的に設計し、それによって作成されたリソースによってフラグメント遷移させるものです。 Navigation コンポーネント スタートガイド | Android Developers https://developer.android.com/guide/navigation/navigation-getting-started?hl=ja [Android] 10分で作る、Navigationによる画面遷移 | Qiita https://qiita.com/tktktks10/items/7df56b4795d907a4cd31 これを利用してフラグメント遷移することも検討してみてはどうでしょうか。 activity_main.xmlにあったfragmentタグは、このNavigationによる遷移を司るものなので、元々あったBottom Navigationの操作による画面遷移が機能しなくなっていると思います。(もちろんNavigationを用いずBottom Navigationの操作による画面遷移を実装することもできますが)
atRhod

2020/09/24 11:21

keicha_hrs様 再度ご回答を頂き、ありがとうございます。 「R.id.nav_view」ではなく、「R id nav_host」でした。失礼致しました。 homeFragment内のreplace文を書き換え、 fragmentTransaction.replace(R.id.nav_host, categoryFragment) としましたが、やはり、クラッシュするようです。エラーは、nav_hostが見つからないものによるもののようです。 java.lang.IllegalArgumentException: No view found for id 0x7f090092 (com.example.electformula:id/nav_host) for fragment CategoryFragment{36d1ceb9 (84f10a45-a685-4d53-8a3f-db3601e0279c) id=0x7f090092} また、試しになっているか分かりませんが…質問に貼り付けている画像に「main activity text」の文字がお見えでしょうか。(こちら、関係ないと考えTeraTail移植時にコードは削除していました)。 こちらはFrameLayout内に書いたTextViewになります。この文字はMainActivityのonCreate時に即座にreplaceされるはずなので、本来消えていなくてはなりません。しかし消えてないところをみると、onCreate内のreplaceも正常に処理を行えていないようです。
atRhod

2020/09/24 11:30

プロジェクト作成時、Bottom Navigation Activityを選びましたので、navigationフォルダも確認いたしました。 教えていただいたリンクの仕組みを利用してフラグメント推移を作成してみようと思います。申し訳ございません、ベストアンサーや解決済等まで少々お時間を頂きます… PS) また、元々あった画面推移の件、ご指摘の通り今回試している過程で動かなくなっております。仕方なく追加の方法を模索しようと思っていましたが、リンクのやり方でFragmentが全て動くのであれば大変助かります。
atRhod

2020/09/25 12:51

教えて下さった「10分で作る、Navigationによる画面遷移 | Qiita」(https://qiita.com/tktktks10/items/7df56b4795d907a4cd31)のNavigationの仕組みを利用して、正常な画面推移を行うことができるようになりました。 また、データの受け渡しは以下のサイトが参考になりました。 「NavigationでSafeArgsを使って引数付き画面遷移をする」(https://qiita.com/tktktks10/items/c78fe6f2083611676fbb) ようやく先に進むことができます。この度はありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問