表示だけのことですので、リストデータを弄る必要はありません。
complete と表示したい position のデータを求められたら complete のレイアウトデータを返すようにし、 それ以降のデータを求められたら position-1 の位置の実際のデータを返すだけです。
Room は関係しなくても良さそうですので、表示部分だけテキトウに作って見ました。
(単に kotlin も Room も不慣れ(or ほぼ分からない)なだけですが...)
kotlin
1package com.teratail.q372341
2
3import android.os.Bundle
4import android.view.LayoutInflater
5import android.view.View
6import android.view.ViewGroup
7import android.widget.CheckBox
8import android.widget.TextView
9import androidx.appcompat.app.AppCompatActivity
10import androidx.lifecycle.MutableLiveData
11import androidx.lifecycle.ViewModel
12import androidx.lifecycle.ViewModelProvider
13import androidx.recyclerview.widget.LinearLayoutManager
14import androidx.recyclerview.widget.RecyclerView
15
16class MainActivity : AppCompatActivity() {
17 override fun onCreate(savedInstanceState: Bundle?) {
18 super.onCreate(savedInstanceState)
19 setContentView(R.layout.activity_main)
20
21 val adapter = ToDoAdapter()
22 val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
23 recyclerView.adapter = adapter
24 recyclerView.layoutManager = LinearLayoutManager(this)
25
26 val todoViewModel = ViewModelProvider(this).get(ToDoViewModel::class.java)
27 todoViewModel.readAllData.observe(this, { todo -> adapter.setData(todo) })
28
29 todoViewModel.add(ToDo(1, false, "todo 1"))
30 todoViewModel.add(ToDo(2, true, "todo 2"))
31 todoViewModel.add(ToDo(3, false, "todo 3"))
32 }
33}
34
35data class ToDo(
36 val id: Int,
37 val complete: Boolean,
38 val text: String
39)
40
41class ToDoAdapter: RecyclerView.Adapter<ToDoAdapter.ToDoViewHolder>() {
42 private var todoList = emptyList<ToDo>()
43 private val layouts = arrayOf(R.layout.recyclerview_item, R.layout.recyclerview_separator)
44
45 class ToDoViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
46 val checkBox: CheckBox?
47 val textView: TextView?
48 init {
49 checkBox = itemView.findViewById(R.id.checkBox)
50 textView = itemView.findViewById(R.id.textView)
51 }
52 }
53
54 override fun getItemViewType(position: Int) = if(position == separateIndex()) 1 else 0
55
56 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
57 ToDoViewHolder(LayoutInflater.from(parent.context).inflate(layouts[viewType], parent, false))
58
59 override fun getItemCount() = todoList.size + if(separateIndex() >= 0) 1 else 0
60
61 override fun onBindViewHolder(holder: ToDoViewHolder, position: Int) {
62 val separateIndex = separateIndex()
63 if(position == separateIndex) return //セパレータに表示するデータは無い
64
65 val pos = position - if(position > separateIndex) 1 else 0
66 val todo = todoList[pos]
67 holder.checkBox?.isChecked = todo.complete
68 holder.textView?.text = todo.text
69 }
70
71 fun setData(todoList: List<ToDo>) {
72 this.todoList = todoList.sortedWith(compareBy<ToDo> { it.complete }.thenBy { it.id })
73 notifyDataSetChanged()
74 }
75
76 private fun separateIndex() = todoList.indexOfFirst { it.complete }
77}
78
79class ToDoViewModel() : ViewModel() {
80 private var allData : MutableList<ToDo> = mutableListOf()
81 val readAllData = MutableLiveData<List<ToDo>>(allData)
82
83 fun add(todo: ToDo) {
84 allData.add(todo)
85 readAllData.value = allData //LiveData発火
86 }
87}
res/layout/activity_main.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <androidx.recyclerview.widget.RecyclerView
11 android:id="@+id/recyclerview"
12 android:layout_width="0dp"
13 android:layout_height="0dp"
14 app:layout_constraintBottom_toBottomOf="parent"
15 app:layout_constraintLeft_toLeftOf="parent"
16 app:layout_constraintRight_toRightOf="parent"
17 app:layout_constraintTop_toTopOf="parent" />
18
19</androidx.constraintlayout.widget.ConstraintLayout>
res/layout/recyclerview_item.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 android:layout_width="match_parent"
6 android:layout_height="wrap_content">
7
8 <CheckBox
9 android:id="@+id/checkBox"
10 android:layout_width="wrap_content"
11 android:layout_height="wrap_content"
12 app:layout_constraintLeft_toLeftOf="parent"
13 app:layout_constraintTop_toTopOf="parent" />
14
15 <TextView
16 android:id="@+id/textView"
17 android:layout_width="0dp"
18 android:layout_height="wrap_content"
19 app:layout_constraintLeft_toRightOf="@id/checkBox"
20 app:layout_constraintRight_toRightOf="parent"
21 app:layout_constraintBaseline_toBaselineOf="@id/checkBox" />
22
23</androidx.constraintlayout.widget.ConstraintLayout>
res/layout/recyclerview_separator.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 android:layout_width="match_parent"
6 android:layout_height="wrap_content">
7
8 <TextView
9 android:layout_width="0dp"
10 android:layout_height="wrap_content"
11 android:text="Complete"
12 android:layout_marginTop="5dp"
13 android:layout_marginBottom="10dp"
14 android:paddingLeft="5dp"
15 android:background="@drawable/upperline"
16 app:layout_constraintLeft_toLeftOf="parent"
17 app:layout_constraintRight_toRightOf="parent"
18 app:layout_constraintTop_toTopOf="parent" />
19
20</androidx.constraintlayout.widget.ConstraintLayout>
res/drawable/upperline.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
3
4 <item>
5 <shape android:shape="rectangle">
6 <solid android:color="#FFFFFF"/>
7 <stroke android:width="1dp" android:color="#AAAAAA" />
8 </shape>
9 </item>
10
11 <item android:top="1dp">
12 <shape android:shape="rectangle">
13 <solid android:color="#FFFFFF"/>
14 </shape>
15 </item>
16</layer-list>