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

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

ただいまの
回答率

87.59%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,160

score 10

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

実現したいこと

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

イメージ説明

問題点

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

イメージ説明

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

試したこと

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

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 下部のナビの部分 -->
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />


    <!-- このフレームレイアウトは仮。MainActivityのonCreateとともにホームフラグメントへ置き換えられる -->
    <FrameLayout
        android:id="@+id/nav_host"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="70dp"
        >
    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity(){
   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //メイン画面の読み込み
        setContentView(R.layout.activity_main)
        //ページ下部のナビ部分を読み込み
        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        //FlameLayoutを即座に、最初のfragment「homeFragment」のリストで上書きする
        var homeFragment: HomeFragment = HomeFragment()
        val fragmentManager = supportFragmentManager
        val transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.nav_host, homeFragment)
        transaction.commit()
    }
}

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

class HomeFragment : Fragment() {
   override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.list_view, container, false)
        return root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // ListViewに表示するデータを読み込む
        val homeArray = resources.getStringArray(R.array.home_array)
        // ListViewをセット
        val adapter =
            this.context?.let { ArrayAdapter<String>(
                it,
                android.R.layout.simple_list_item_1,
                homeArray
            ) }
        val listView: ListView = view.findViewById(R.id.listView) as ListView
        listView.adapter = adapter

        // listViewの行がクリックされた時のイベントリスナー
        listView.setOnItemClickListener { parent, view, position, id ->

            //次のフラグメント「カテゴリフラグメント」を表示する 
            val fragmentManager: FragmentManager = childFragmentManager

            // FragmentManagerからFragmentTransactionを作成
            val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()

            //  次のリストとなるFragmentの作成
            val categoryFragment: Fragment = CategoryFragment()

            // 次のフラグメントへreplace
            fragmentTransaction.replace(R.id.list, categoryFragment)

            // backstackに追加 → 端末の戻るボタン押した時に、このアクティビティに戻ってくる設定にする
            fragmentTransaction.addToBackStack(null)

            // 上記の変更を反映する
            fragmentTransaction.commit()
        }
    }
}

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

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/list"
    tools:context=".ui.home.HomeFragment">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        >
    </ListView>
</androidx.constraintlayout.widget.ConstraintLayout>

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/24 20: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も正常に処理を行えていないようです。

    キャンセル

  • 2020/09/24 20:30

    プロジェクト作成時、Bottom Navigation Activityを選びましたので、navigationフォルダも確認いたしました。
    教えていただいたリンクの仕組みを利用してフラグメント推移を作成してみようと思います。申し訳ございません、ベストアンサーや解決済等まで少々お時間を頂きます…

    PS)
    また、元々あった画面推移の件、ご指摘の通り今回試している過程で動かなくなっております。仕方なく追加の方法を模索しようと思っていましたが、リンクのやり方でFragmentが全て動くのであれば大変助かります。

    キャンセル

  • 2020/09/25 21:51

    教えて下さった「10分で作る、Navigationによる画面遷移 | Qiita」(https://qiita.com/tktktks10/items/7df56b4795d907a4cd31)のNavigationの仕組みを利用して、正常な画面推移を行うことができるようになりました。

    また、データの受け渡しは以下のサイトが参考になりました。
    「NavigationでSafeArgsを使って引数付き画面遷移をする」(https://qiita.com/tktktks10/items/c78fe6f2083611676fbb

    ようやく先に進むことができます。この度はありがとうございました。

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る