
We will be starting with a new series where I’ll create the notes app, the project is quite big so it will take around four videos to complete it.
Also, we will be covering four major advanced topics which are MVVM, Room Database, Coroutines, and Navigation Component in one single project. So, I highly recommend revising each topic before starting with the project.
Topic Videos:
Alright, let’s have a look at the demo.
This is how it looks!
I have kept the project very minimal and useful.

This will be the first screen to be displayed when there are no notes available basically in an empty notes app.
Also, there will be a floating action button which will redirect to AddNoteFragment where you can add a new note.

This is AddNoteFragment where you can add a note title and note description.
Also, there is a save button on the action bar.

This is HomeFragment, here all the notes will be displayed in a recyclerview using the staggered layout.
Also, this is the same page where empty notes were displayed but if notes are available then obviously the recyclerview will be displayed and at the top of the action bar there is a search view.

Then, this is EditNoteFragment where you can edit the note and through the floating action button, you can save the edited note.

Also, you can delete the note that is present in EditNoteFragment at the top of the action bar.
All, of these, might look very easy to you and it is indeed very easy…it’s, just that we have to write a lot of code for them.
Now, before starting with all the prerequisites…let, me quickly tell you the technical side of it, also it will be great if you guys are using the latest version of Android Studio Hedgehog 2023.1.1.
So first, there will be a blank screen if no notes are available but if there are notes available then it will display in a recycler view using a staggered layout…for, that we will require an adapter, right?
Then, notes will be saved in the room database… those, three main components are: entity, dao, and database, correct? then, they all will be handled under the repository…then, we have viewmodel for the communication…and, lastly we will have three fragments: AddNote fragment where we will add a note, EditNote fragment where we will edit the note, and HomeFragment where we will display the notes, simple right? also, the delete feature will be handled in the EditNoteFragment, and the search feature will be handled in the HomeFragment, got it?
Note: This is my practice project which works the same way as the original one but please copy only the required code because copying the entire code of gradle or manifest will lead to errors related to the project package name.
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="pink">#F88379</color>
<color name="red">#c13b34</color>
</resources>
themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.NotesRoomPractice." parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/pink</item>
<item name="colorPrimaryVariant">@color/pink</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/pink</item>
<item name="colorSecondaryVariant">@color/pink</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
strings.xml
<resources>
<string name="app_name">Notes</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
Drawables:
pink_border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="@color/pink"/>
<corners
android:radius="8dp"/>
</shape>
Download Empty Background Image

build gradle (Project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
}
dependencies {
val navVersion = "2.7.5"
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$navVersion")
}
}
plugins {
id ("com.android.application") version "7.3.1" apply false
id ("com.android.library") version "7.3.1" apply false
id ("org.jetbrains.kotlin.android") version "1.7.20" apply false
id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false
}
build gradle (Module)
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id ("kotlin-kapt")
id ("kotlin-parcelize")
id("com.google.devtools.ksp")
id ("androidx.navigation.safeargs")
}
android {
namespace = "com.example.notesroompractice"
compileSdk = 34
defaultConfig {
applicationId = "com.example.notesroompractice"
minSdk = 28
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures{
dataBinding = true
}
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.10.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
// ROOM
val roomVersion = "2.6.1"
implementation ("androidx.room:room-runtime:$roomVersion")
ksp("androidx.room:room-compiler:$roomVersion")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
implementation ("androidx.room:room-ktx:$roomVersion")
// Navigation
val navVersion = "2.7.5"
implementation("androidx.navigation:navigation-fragment-ktx:$navVersion")
implementation("androidx.navigation:navigation-ui-ktx:$navVersion")
// Life Cycle Arch
val lifecycleVersion = "2.6.2"
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion")
// Annotation processor
ksp("androidx.lifecycle:lifecycle-compiler:$lifecycleVersion")
}
home_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/searchMenu"
android:icon="@drawable/ic_search"
android:title="Search"
app:showAsAction="ifRoom"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>
menu_add_note.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/saveMenu"
android:title="Save"
app:showAsAction="always" />
</menu>
menu_edit_note.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/deleteMenu"
android:icon="@drawable/baseline_delete_24"
android:title=""
app:showAsAction="always"/>
</menu>
Packages and Fragments

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NotesRoomPractice."
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value=""/>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>
fragment_home.xml
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeFragment">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/addNoteFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginBottom="28dp"
android:backgroundTint="@color/pink"
android:clickable="true"
android:contentDescription="image"
android:tintMode="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_add" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/homeRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/emptyNotesImage"
android:visibility="gone"
android:src="@drawable/emptybkg"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_add_note.xml
<?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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".NewNoteFragment"
android:padding="12dp">
<TextView
android:id="@+id/addNoteHeading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="16dp"
android:fontFamily="@font/poppins"
android:text="Add Note."
android:textStyle="bold"
android:textColor="@color/red"
android:textSize="24sp" />
<EditText
android:id="@+id/addNoteTitle"
android:layout_width="match_parent"
android:layout_height="60dp"
android:hint="Enter the title"
android:padding="12dp"
android:textSize="20sp"
android:layout_below="@id/addNoteHeading"
android:background="@drawable/pink_border"
android:layout_marginTop="16dp"
android:maxLines="1"
android:fontFamily="@font/poppins"/>
<EditText
android:id="@+id/addNoteDesc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="Enter the description"
android:gravity="top"
android:padding="12dp"
android:textSize="18sp"
android:fontFamily="@font/poppins"
android:background="@drawable/pink_border"
android:layout_below="@id/addNoteTitle"
android:layout_marginTop="12dp" />
</RelativeLayout>
</layout>
fragment_edit_note.xml
<?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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="12dp"
tools:context=".UpdateNoteFragment">
<TextView
android:id="@+id/editNoteHeading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="16dp"
android:fontFamily="@font/poppins"
android:text="Edit Note."
android:textStyle="bold"
android:textColor="@color/red"
android:textSize="24sp" />
<EditText
android:id="@+id/editNoteTitle"
android:layout_width="match_parent"
android:layout_height="60dp"
android:hint="Enter the title"
android:padding="12dp"
android:textSize="20sp"
android:layout_below="@id/editNoteHeading"
android:background="@drawable/pink_border"
android:layout_marginTop="16dp"
android:maxLines="1"
android:fontFamily="@font/poppins"/>
<EditText
android:id="@+id/editNoteDesc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="Enter the description"
android:gravity="top"
android:padding="12dp"
android:textSize="18sp"
android:fontFamily="@font/poppins"
android:background="@drawable/pink_border"
android:layout_below="@id/editNoteTitle"
android:layout_marginTop="12dp" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/editNoteFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:clickable="true"
android:backgroundTint="@color/pink"
android:tintMode="@color/white"
android:src="@drawable/ic_done"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:contentDescription="editFab" />
</RelativeLayout>
</layout>
note_layout.xml
<?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">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="6dp"
app:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/pink_border"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/noteTitle"
android:layout_weight="200"
android:textColor="@color/red"
android:fontFamily="@font/poppins"
android:text="Note Title"
android:textStyle="bold"
android:textSize="18sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/noteDesc"
android:layout_marginTop="8dp"
android:maxHeight="170dp"
android:text="Description"
android:textSize="14sp"
android:fontFamily="@font/poppins"
android:textColor="@color/pink"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>
activity_main.xml
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
nav_graph.xml
<?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"
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.notesroompractice.fragments.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@+id/action_homeFragment_to_addNoteFragment"
app:destination="@id/addNoteFragment" />
<action
android:id="@+id/action_homeFragment_to_editNoteFragment"
app:destination="@id/editNoteFragment" />
</fragment>
<fragment
android:id="@+id/addNoteFragment"
android:name="com.example.notesroompractice.fragments.AddNoteFragment"
android:label="fragment_add_note"
tools:layout="@layout/fragment_add_note" >
<action
android:id="@+id/action_addNoteFragment_to_homeFragment"
app:destination="@id/homeFragment" />
</fragment>
<fragment
android:id="@+id/editNoteFragment"
android:name="com.example.notesroompractice.fragments.EditNoteFragment"
android:label="fragment_edit_note"
tools:layout="@layout/fragment_edit_note" >
<action
android:id="@+id/action_editNoteFragment_to_homeFragment"
app:destination="@id/homeFragment" />
<argument
android:name="note"
app:argType="com.example.notesroompractice.model.Note"
app:nullable="true" />
</fragment>
</navigation>
All our prerequisites are done and now from the next video, the real logic begins…so, make sure you watch all the parts from the notes app playlist.
Also, for more updates you can follow us on Instagram or join our telegram group – @android_knowledge
You can create a splash screen if you want to – click here for the code
Please subscribe to my YouTube channel:
Android Knowledge – Click here