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のコードに書くなってことかな?)
コメント