Reading Time: 11 minutesIn this chapter of the Room basics tutorial we are going to create the starter project. It means, that we are going to add the needed dependencies, add the fragments, implement the RecyclerView, which will hold our todos, create the data class and finally we will create the navigation graph as well.
Because we will use in this tutorial Kotlin Coroutines, Navigaion– and Lifecycle components, we have to add to the project some other dependencies. Thenafter we can start to implement the RecyclerView for our todos.
So, let’s start coding! 😎
Jump
As you can see, this chapter is a bit longer and it still doesn’t contain to much things about Room. In this chapter we are going to prepare the sample project to use Room.
If you want, then you can jump to the next chapter, because there you can continue the tutorial from the end of this chapter.
BUT, we highly recommend you to do this chapter as well. Why? Because, if you want to be a good programmer, then you have to practice all the time, and this chapter is a good opportunity for this.
Step 1 – Create new project
Our first step is to create a whole new project. For this, launch Android Studio and create a new project. If you see the “Welcome page” of Android Studio, then click on the “Start a new Android Studio project”.
If you have an open project, then from the “File” menu select “New”, then “New Project”. After thet, this window will popup.
Here select the “Empty Activity” option.
In the next window, we should provide some information about the newly created app.
As always, this tutorial will be written in Kotlin. So, select from the dropdown list the Kotlin language.
From the next list of the “Minimum SDK” select API 21. In our case API 21 gonna be enough.
There is a link, called “Help me choose”. If you click on it, then a colorful figure will show you the different Android versions and their imported innovations.
If you are done, click on the “Finish” button. The build can take few minutes. Be patient! 😉
When the build has been finished, then you should see the open MainActivity:class and next to this the activity_main.xml files. For now you can close both of them.
Step 2 – Add the needed dependencies
Next step is to enable for the project the dependencies, what we are going to use.
So, to add them to the project, go to the top left corner of Android Studio. There will be the tab called “Project”. Click on it and change the view to Android. Then open the Gradle Scripts menu and double click on the build.gradle (Module: app) file.
Kotlin Annotation Processing Tool
In the top of the file you will find some lines, which are starting like “apply plugin:…”. There paste the below line:
apply plugin: ‘kotlin-kapt’
This will enable us to use the Kotlin annotations in our project. It is needed, because we will use many annotations for Room.
Enable Safe Args
When we will modify an item from the RecyclerView, we will pass a ToDo object to the modification dialog. We can pass this data class with the Safe Args extension of the Navigation Component. To enabled them paste the below line after the previuos one.
apply plugin: ‘androidx.navigation.safeargs.kotlin’
Set the target JVM
Now, go a bit down, until the end of the android {} section. There paste the below lines also.
android {
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
Target JVM
We need these line to use Navigation Componenets.
Enable Data Binding
Also here, after the JVM lines, paste the below lines also. These will enable in the project Data Binding.
android {
dataBinding {
enabled true
}
}
Enabling Data Binding
Dependencies
Next is to add the dependencies. They are going to the dependencies {} section of the build.gradle (Module: app) file.
Copy and paste the below lines at the end of the dependencies.
/** Navigation **/
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
/** Room components **/
implementation "androidx.room:room-runtime:$roomVersion"
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
/** Lifecycle components **/
implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-common-java8:$archLifecycleVersion"
/** Kotlin Coroutines **/
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines"
Dependencies
The versions
The last step before we can synchronize the app is to define the versions of the above mentioned dependencies. We are going to do it in one place, which is located in the build.gradle (Project: app) file. You can find this file next the build.gradle (Module: app) file.
At the top of the file, inside of the buildscript{} section you should have the version of Kotlin.
After it paste the needed versions. After thet the versions should look like below.
ext.archLifecycleVersion = '2.2.0'
ext.kotlinCoroutines = '1.3.7'
ext.kotlin_version = '1.3.72'
ext.navigationVersion = '2.3.0-beta01'
ext.roomVersion = '2.2.5'
The versions
Safe Args, one more thing
Ok, I promise, this will be the very last thing, what we have to do before synching. 😊
To use Safe Args, we have to add it to the build.gradle (Project: app) file also. Inside of the buildscript{} section should be a subsection, called dependencies{}.
Copy and paste there the below line.
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
Safe Args Vol.2
Sync the project
Finally click on the “Sync Now” text, what you can find at the top right corner of Android Studio.
This can take some minutes, so be patient. 😊
Step 3 – Create the fragments
In this application we will have two screens. The first one will contain the RecyclerView, the second one will be responsible to create and modify the ToDos.
RecyclerViewFragment
So, click with the right mouse button on the name of the package from the left “Project” tab. Then, in the menu select New, then Package. In the popup window name this package as “fragments”. In this folder will be the two fragments.
Now, click on this new package again with the right mouse button, select New, and in this case go the Fragment and select the Fragment (Blank) option. Give it the name of “RecyclerViewFragment” and click on the Finish button.
Android Studio will automatically open for us the RecyclerViewFragment::class. There, we have many lines of code, what we don’t need. So, remove all of the not needed lines and paste the below code in place of them.
class RecyclerFragment : Fragment()
{
private val toDoViewModel by navGraphViewModels(R.id.navigation_graph)
private lateinit var toDoAdapter: ToDoAdapter
private val itemTouchHelper_reOrder by lazy {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.START or ItemTouchHelper.END, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)
{
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean
{
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
{
val from = viewHolder.adapterPosition
toDoViewModel.deleteToDo(toDoAdapter.getItemFromPosition(position = from))
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int)
{
super.onSelectedChanged(viewHolder, actionState)
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder)
{
super.clearView(recyclerView, viewHolder)
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
override fun onStart()
{
super.onStart()
(activity as AppCompatActivity).supportActionBar?.show()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View?
{
val view = inflater.inflate(R.layout.fragment_recycler, container, false)
context?.let { _context ->
toDoAdapter = ToDoAdapter(_context)
binding.recyclerView.apply {
layoutManager = LinearLayoutManager(context)
adapter = toDoAdapter
}
}
toDoViewModel.listOfToDosLiveData.observe(viewLifecycleOwner, Observer { _list ->
toDoAdapter.addToDos(_list)
toDoAdapter.notifyDataSetChanged()
})
itemTouchHelper_reOrder.attachToRecyclerView(view.recyclerView)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
super.onViewCreated(view, savedInstanceState)
fab_add.setOnClickListener {
findNavController().navigate(R.id.action_recyclerFragment_to_addToDoDialog)
}
}
}
RecyclerViewFragment
After the paste you will have some errors. Don’t worry, we are going to fix them later on in this chapter.
Now, open up the fragment_recycler_view.xml file from the res->layout folders.
First, change the rootview from FrameLayout to ConstraintLayout. Then, move your cursor to the ConstraintLayout. Press there on you keyboard the Alt+Enter hot keys on Windows or Control/Option+Enter on Mac. This will open up a quick menu, the Show Context Actions menu. There, select the first option, which is “Convert to data binding layout”.
After the conversions, we will add the RecyclerView and a Floating Action Button to the layout.
The result should look like below.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.RecyclerViewFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_add"
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_margin="26dp"
app:srcCompat="@drawable/ic_add"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_recycler_view.xml
Add the ic_add image
After the past, you will have an error, because our project still doesn’t contain the ic_add image.
So, click again with the right mouse button on the drawable folder, which is located in the res directory. From the menu select New, then Vector Asset option. By default, the Android icon will be there. Click on it in the line of Clip Art. Type in the search field “add” and select from the right icons the add icon, then click on the OK button, name the icon as “ic_add“. Finally, click on the Next and Finish buttons.
The error shouldn’t be there anymore. 😎
Change the class
To start using Data Binding, we have to change the RecyclerViewFragment::class again a bit.
Add the next line as a member variable.
private lateinit var binding: FragmentRecyclerViewBinding
Then initialize the binding variable in the onCreate() method.
binding = DataBindingUtil.inflate(
layoutInflater,
R.layout.fragment_recycler_view,
container,
false
)
AddToDoDialog
The second fragment is the AddToDoDialog. As we have done it before, create a new blank fragment in the fragments package.
Now, open the fragment_add_to_do_dialog.xml file from the layout folder, which is in the res directory.
Already now, we are going to add the needed views to the layout. So, replace the current xml code with the below lines.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lightGrey"
android:padding="12dp"
tools:context=".fragments.AddToDoDialog">
<TextView
android:id="@+id/tv_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="Add ToDo"
android:textColor="@color/white"
android:textSize="20sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/horizontalLine"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="@color/white"
app:layout_constraintTop_toBottomOf="@+id/tv_dialog_title" />
<TextView
android:id="@+id/tv_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title"
android:layout_marginTop="16dp"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@+id/horizontalLine" />
<EditText
android:id="@+id/et_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/white"
android:textSize="16sp"
android:textColor="@color/darkGrey"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title_text" />
<TextView
android:id="@+id/tv_description_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/white"
android:text="Description"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@+id/et_title" />
<EditText
android:id="@+id/et_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/white"
android:textColor="@color/darkGrey"
android:textSize="16sp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_description_text" />
<TextView
android:id="@+id/tv_priority_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Priority"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@+id/et_description" />
<LinearLayout
android:id="@+id/ll_priority"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_priority_text">
<Spinner
android:id="@+id/sr_priority"
style="@style/Widget.AppCompat.DropDownItem.Spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_dueDate_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Due date"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@+id/ll_priority" />
<DatePicker
android:id="@+id/dp_dueDate"
style="@android:style/Widget.DatePicker"
android:layout_width="wrap_content"
android:layout_height="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_dueDate_text" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/colorPrimary"
android:background="@color/white"
android:layout_marginTop="40dp"
app:layout_constraintTop_toBottomOf="@+id/dp_dueDate"
app:layout_constraintRight_toRightOf="parent"
android:text="Add" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel"
android:textColor="@color/white"
android:textSize="20sp"
android:layout_marginEnd="32dp"
app:layout_constraintRight_toLeftOf="@+id/btn_add"
app:layout_constraintTop_toTopOf="@+id/btn_add"
app:layout_constraintBottom_toBottomOf="@+id/btn_add" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_add_to_do_dialog.xml
The colors
The colors are defined in the colors.xml file. You can find it in the values folder, what you can find in the res directory.
Repleace its value with the below colors.
<color name="colorPrimary">#1DA1D2</color>
<color name="colorPrimaryDark">#78C257</color>
<color name="colorAccent">#FFBD2A</color>
<color name="lightGrey">#9A9A9B</color>
<color name="darkGrey">#464E5B</color>
<color name="white">#EAEFF6</color>
<color name="blue">#1DA1D2</color>
<color name="orange">#F88909</color>
colors.xml
If you don’t like these colors, then you can change them by your own, it depends on you. 😀
The AddToDoDialog::class
In this tutorial we won’t go into the detailes of how you we can implement this dialog, nor the RecyclerView.
So, copy and repleace the current code of the AddToDoDialog::class with the below one.
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.navArgs
import com.inspirecoding.roombasics.R
import com.inspirecoding.roombasics.databinding.FragmentAddToDoDialogBinding
import kotlinx.android.synthetic.main.fragment_add_to_do_dialog.*
class AddToDoDialog : DialogFragment()
{
private lateinit var binding: FragmentAddToDoDialogBinding
override fun onCreateView(layoutInflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
binding = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_add_to_do_dialog, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
super.onViewCreated(view, savedInstanceState)
val safeArgs: AddToDoDialogArgs by navArgs()
val toDo = safeArgs.toDo
initSpinner()
toDo?.let {
binding.tvDialogTitle.text = getString(R.string.modify_todo)
binding.btnAdd.text = getString(R.string.modify)
populateForm(it)
}
binding.tvCancel.setOnClickListener {
dismiss()
}
binding.btnAdd.setOnClickListener {
if(toDo != null)
{
val updatedToDo = createToDo()
updatedToDo.toDoId = toDo.toDoId
}
else
{
}
dismiss()
}
}
private fun populateForm(toDo: ToDo)
{
binding.etTitle.setText(toDo.title)
binding.etDescription.setText(toDo.description)
when(toDo.priority)
{
Prioirities.LOW.name -> rootView.sr_priority.setSelection(0)
Prioirities.MEDIUM.name -> rootView.sr_priority.setSelection(1)
Prioirities.HIGH.name -> rootView.sr_priority.setSelection(2)
}
val day = toDo.dueDate.substringBefore('.').toInt()
val month = toDo.dueDate.substringBeforeLast('.').substringAfter('.').toInt()
val year = toDo.dueDate.substringAfterLast('.').toInt()
binding.dpDueDate.updateDate(year, month, day)
}
private fun initSpinner()
{
activity?.let {
val arraySpinner = arrayOf (
it.getString(R.string.low),
it.getString(R.string.medium),
it.getString(R.string.high)
)
val adapter: ArrayAdapter = ArrayAdapter(it.applicationContext, android.R.layout.simple_spinner_item, arraySpinner)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
sr_priority.adapter = adapter
}
}
private fun createToDo() = ToDo(
0,
binding.etTitle.text.toString(),
"${String.format("%02d", binding.dpDueDate.dayOfMonth)}.${String.format("%02d", binding.dpDueDate.month)}.${String.format("%04d", binding.dpDueDate.year)}",
binding.etDescription.text.toString(),
when(binding.srPriority.selectedItemId)
{
0L -> Prioirities.LOW.name
1L -> Prioirities.MEDIUM.name
else -> Prioirities.HIGH.name
}
)
}
AddToDoDialog::class
Don’t worry because of the many errors, we are going to fix them.
Strings.xml
First open the strings.xml file from the res->values folders and replace the values with the below lines.
<resources>
<string name="app_name">RoomBasics</string>
<string name="title">ToDo Title</string>
<string name="duedate">03.11.1988</string>
<string name="placeholder_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</string>
<string name="low">Low</string>
<string name="medium">Medium</string>
<string name="high">High</string>
<string name="modify_todo">Modify ToDo</string>
<string name="modify">Modify</string>
</resources>
strings.xml
Step 4 – Enum of Prioirities
We are going to use an enum to identify the priority of the todo items.
What does enum mean? Check out our tutorial.
Enum
For this enum, we are going to create a new package, called “enums”. Do it as we have done it in case of the “fragments” package.
Insid of the “enums” package create a new Kotlin file. So, click on it with the right mouse button, and from the menu select New, then Kotlin file/class. Then name it as “Prioirities”.
Paste the below few lines into the Prioirities::enum.
enum class Prioirities
{
LOW,
MEDIUM,
HIGH
}
Prioirities
Now, go back to the AddToDoDialog::class and import the Prioirities::enum, there move the cursor to the error and press there on you keyboard the Alt+Enter hot keys on Windows or Control/Option+Enter on Mac. This will open up a quick menu, the Show Context Actions menu. There, select the first option, which is the Import.
Step 5 – Create the ToDo data class
The next step in this chapter is to create the ToDo data class. This class will hold the data for a todo item and this will be shown in the RecyclerView as well.
Don’t you know what does data class mean? Check out our tutorial.
Data Class
For the ToDo data class create again a new package, called “model”, then create inside of it a Kotlin file, which has the name of “ToDo”. Thenafter paste the below into it.
@Parcelize
data class ToDo (
var toDoId: Int,
var title: String,
var dueDate: String,
var description: String,
var priority: String
) : Parcelable
data class ToDo
Again, go back to the AddToDoDialog::class and import the ToDo::class there.
Step 6 – The adapter for the RecyclerView
We have three things left, what we are going to in this chapter. The first one is the adapter, which will handle the items of the RecyclerView.
Download the assets
The items of the RecyclerView will show us the priority of the ToDo item. For this, we are going to use a green, an orange and a red circle. You can download them using the below link.
Donwload assets
After the donwload, unzip the files into the your project’s res folder.
Layout of the item
Next, we have to create the layout of the item as well. So click with the right mouse button on the layout folder from the res directory, then select New and Layout Resource file. In the popup window name the new file as “item_todo_recyclerview”.
Copy and paste the below code into the new layout file.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<com.google.android.material.card.MaterialCardView
android:id="@+id/mcv_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="8dp"
app:cardCornerRadius="4dp"
android:layout_margin="16dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimary"
android:textSize="20dp"
tools:text="@string/title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/tv_dueDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/darkGrey"
android:textSize="12dp"
tools:text="@string/duedate"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/tv_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginRight="11dp"
android:textColor="@color/darkGrey"
android:textSize="16dp"
tools:text="@string/placeholder_text"
app:layout_constraintTop_toBottomOf="@+id/tv_dueDate"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_priority" />
<ImageView
android:id="@+id/iv_priority"
android:layout_width="50dp"
android:layout_height="50dp"
tools:src="@drawable/prio_green"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
item_todo_recyclerview.xml
The adapter
After the item, we can create the adapter for the RecyclerView as well. As before, create again a new package called “adapter” and create inside of it a new Kotlin file, called “ToDoAdapter”.
Copy and paste there the below code.
class ToDoAdapter(val context: Context): RecyclerView.Adapter()
{
private var listOfToDos = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoAdapter.ToDoHolder
{
val layoutInflater = LayoutInflater.from(context)
val binding: ItemTodoRecyclerviewBinding = DataBindingUtil.inflate(
layoutInflater,
R.layout.item_todo_recyclerview, parent, false
)
return ToDoHolder(binding)
}
override fun getItemCount() = listOfToDos.size
internal fun addToDos(listOfToDos: List)
{
this.listOfToDos = listOfToDos
notifyDataSetChanged()
}
internal fun getItemFromPosition(position: Int): ToDo
{
return listOfToDos[position]
}
override fun onBindViewHolder(holder: ToDoAdapter.ToDoHolder, position: Int)
{
holder.bindToDo(listOfToDos[position])
}
inner class ToDoHolder(val binding: ItemTodoRecyclerviewBinding): RecyclerView.ViewHolder(binding.root), View.OnClickListener
{
init {
binding.root.setOnClickListener(this)
}
fun bindToDo(toDo: ToDo)
{
binding.tvTitle.text = toDo.title
binding.tvDueDate.text = toDo.dueDate
binding.tvDescription.text = toDo.description
when (toDo.priority)
{
Prioirities.LOW.name -> binding.ivPriority.setBackgroundResource(R.drawable.prio_green)
Prioirities.MEDIUM.name -> binding.ivPriority.setBackgroundResource(R.drawable.prio_orange)
Prioirities.HIGH.name -> binding.ivPriority.setBackgroundResource(R.drawable.prio_red)
}
}
override fun onClick(view: View)
{
val navController: NavController = Navigation.findNavController(view)
val action = RecyclerViewFragmentDirections.actionRecyclerFragmentToAddToDoDialog(listOfToDos[adapterPosition], adapterPosition)
navController.navigate(action)
}
}
}
ToDoAdapter
Agaaain… an error??? 😡
Don’t worry. In the next step the navigation_graph will solve this as well. 😎
Step 7 – The Navigation Component
The Navigation Component will be responsible for the navigation inside of the app, and it will help us to pass the ToDo item, when we want to modify it.
The navigation_graph
Do you know what will be the next step? Yes, of course, a new directory. 😀
Create a new directory called “navigation” inside of the res folder. Then in this folder create a new resource file, called “navigation_graph”.
Then paste there the below code.
<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
app:startDestination="@+id/recyclerFragment"
android:id="@+id/navigation_graph">
<dialog
android:id="@+id/addToDoDialog"
android:name="com.inspirecoding.roombasics.fragments.AddToDoDialog"
android:label="fragment_add_to_do_dialog"
tools:layout="@layout/fragment_add_to_do_dialog" >
<argument
android:name="toDo"
app:nullable="true"
android:defaultValue="@null"
app:argType="com.inspirecoding.roombasics.model.ToDo"/>
<argument
android:name="position"
android:defaultValue="0"
app:argType="integer"/>
</dialog>
<fragment
android:id="@+id/recyclerFragment"
android:name="com.inspirecoding.roombasics.fragments.RecyclerViewFragment"
android:label="fragment_recycler"
tools:layout="@layout/fragment_recycler_view" >
<action
android:id="@+id/action_recyclerFragment_to_addToDoDialog"
app:destination="@id/addToDoDialog" />
</fragment>
<activity
android:id="@+id/mainActivity"
android:name="com.inspirecoding.roombasics.MainActivity"
android:label="activity_main"
tools:layout="@layout/activity_main" />
</navigation>
navigation_graph
The <fragment>
Aaa finally, the last step, which is an easy one. For the Navigation Component, we have to have a host fragment. It means a simple <fragment> view, which will be in our case in the activity_mail.xml file.
So, open it form the res->layout folder and paste there by replacing the TextView.
<fragment
android:id="@+id/container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:navGraph="@navigation/navigation_graph" />
The host fragment
Run the app
And here it’s time to run the app….. but unfortunetly we can’t do too much things. What you can do now, is to tap on the Floating Action Button and open the dialog, which still doesn’t do anything when you click on the Add button.
GitHub
The source code is available on GitHub
GitHub
Questions
I hope the description was understandable and clear. But, if you have still questions, then leave me a comment below! 😉
Have a nice a day! 🙂
Click to rate this post!
[Total: 0 Average: 0]