FragmentでRecyclerView

Android Studio

RecyclerView(その4)をFragment上に実装して長押し時にPopupMenuを表示するようにした場合の備忘録です。

注意:こうやったら動きましたと言う例です。ドキュメントを完全に理解しているわけではないので、本当に正しいやり方かどうかはわかりません。

環境は以下の通りです。

Android Studio Dolphin | 2021.3.1
Build #AI-213.7172.25.2113.9014738, built on September 1, 2022
Runtime version: 11.0.13+0-b1751.21-8125866 aarch64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 13.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1280M
Cores: 8

RecyclerViewのcellを長押しするとPopupMenuで”追加”、”変更”、”削除”を表示し、クリックするとTextViewにクリックした項目を表示するというものです。

“CustomAdapter.kt”と”list_layout.xml”はその4と同じです。Fragmentのレイアウトはその4のActivityとほぼ同じです。Fragmentのコードはその4のActivityに似ていますが、親のActivityを取得するためのRequireActivity()やrequireContext()などの記述が要るようです。Activity自体はFragmentをのせているだけです。

MainActivity.kt

package com.gmail.san58gong.myrecyclerview02

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recyclerViewFragment = RecyclerViewFragment()
        val transaction = supportFragmentManager.beginTransaction()
        transaction.add(R.id.container1, recyclerViewFragment)
        transaction.commit()

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/container1"
        android:layout_width="409dp"
        android:layout_height="729dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

list_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="TextView" />
</LinearLayout>

menu_popup.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/menu_add"
        android:title="追加" />
    <item
        android:id="@+id/menu_change"
        android:title="変更" />
    <item
        android:id="@+id/menu_delete"
        android:title="削除" />
</menu>

fragment_recycler_view.xml

<?xml version="1.0" encoding="utf-8"?>
<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/ConstraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RecyclerViewFragment">

    <!-- TODO: Update blank fragment layout -->

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment"
        app:layout_constraintBottom_toTopOf="@+id/recycler_view"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

RecyclerViewFragment.kt

package com.gmail.san58gong.myrecyclerview02

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader


class RecyclerViewFragment : Fragment() {
    lateinit var mAdapter: CustomAdapter
    var listArray = emptyList<String>()
    var csvFile: String? = "list.csv"  //csvファイル名

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {


        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_recycler_view, container, false)
    }

    override fun onStart() {
        super.onStart()
        val text2 = requireActivity().findViewById<TextView>(R.id.textView)

        //テキストファイルの読み込み
        readCsv(csvFile!!)
        // RecyclerViewの取得
        val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)

        // LayoutManagerの設定
        recyclerView?.layoutManager = LinearLayoutManager(requireActivity())

        val popupMenu = PopupMenu(
            requireContext(), recyclerView

        )

        popupMenu.menuInflater.inflate(R.menu.menu_popup, popupMenu.menu)

        popupMenu.setOnMenuItemClickListener { menuItem ->
            val id = menuItem.itemId
            if (id == R.id.menu_add) {
                text2?.text = "追加"
            } else if (id == R.id.menu_change) {
                text2?.text = "変更"
            } else if (id == R.id.menu_delete) {
                text2?.text = "削除"
            }
            false
        }

        // CustomAdapterの生成と設定
        mAdapter = CustomAdapter(listArray as ArrayList<String>)
        recyclerView?.adapter = mAdapter

        mAdapter.setOnItemLongClickListener(object :CustomAdapter.OnItemLongClickListener {
            override fun OnItemLongClickListener(view: View, position: Int, clickedText: String) {
                popupMenu.show()
            }
        })


    }


    fun readCsv(filename: String){
        try {
            val file = resources.assets.open(filename)

            val fileReader = BufferedReader(InputStreamReader(file))
            var rd = fileReader.readLine()
            while (rd != null) {
                listArray += rd
                rd = fileReader.readLine()
            }
        }catch (e: IOException) {
            //例外処理
            print(e)
        }
    }
}

RecyclerViewの設定などはFragmentのライフサイクルのonStart以降に記述しないと動きません。クラッシュはしませんがRecyclerViewを表示しません。「親のActivityができる前に書いても処理できないよ」ってことでしょうね。今回はonStartに記述しました。(onActivityCreatedに書いても動きます。ただし、”super call”が消し線付きになります。ragmentのライフサイクルじゃないからfragmentのコードに書くなってことかな?)

コメント

タイトルとURLをコピーしました