How to make a todo list app in android studio using kotlin Skip to main content

Recent Posts

Top Tourist Places in Rajasthan – A Complete Travel Guide 2025

Top Tourist Places in Rajasthan – A Complete Travel Guide 2025 Introduction Rajasthan , the “ Land of Kings ,” is India’s largest state and a treasure trove of history, culture, and natural beauty. From golden deserts to majestic palaces, serene lakes to vibrant festivals, Rajasthan offers something for every traveller. Whether you love heritage, adventure, or photography, this state will capture your heart. 1. Jaipur – The Pink City Keywords: Jaipur tourism, Jaipur tourist places, Rajasthan capital city attractions Amber Fort : A UNESCO World Heritage Site with stunning architecture and elephant rides. City Palace: A royal complex showcasing Rajput and Mughal designs. Hawa Mahal : The “Palace of Winds” with 953 jharokhas . Jantar Mantar : An astronomical observatory. Shopping at Johari Bazaar & Bapu Bazaar. Best Time to Visit: October to March. 2. Udaipur – The City of Lakes Keywords: Udaipur tourist places, best places in Rajasthan for couples ...

How to make a todo list app in android studio using kotlin

 How to make a todo list app in Android Studio using Kotlin

Creating a simple TODO app with three activities (MainActivity, InsertActivity, UpdateActivity) and features like pinning notes, searching, and using a Room database in Android with Kotlin requires several steps. Below is a basic implementation.

 1- Setting Up the Project

  • Create a new Android project in Android Studio.

2- Add dependencies in the build. gradle:

  • Add the Room database dependencies and other necessary libraries.
       dependencies {

    // Room components
    implementation "androidx.room:room-runtime:2.4.3"
    kapt "androidx.room:room-compiler:2.4.3"
    
    // Kotlin components
    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.6.10"
    
    // Lifecycle components
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
    
    // RecyclerView
    implementation "androidx.recyclerview:recyclerview:1.2.1"
    
    // Core components
    implementation "androidx.core:core-ktx:1.7.0"
    
    // Material Design
    implementation "com.google.android.material:material:1.5.0"
}

3-Create data model for the notes:


@Entity(tableName = "notes") data class Note( @PrimaryKey(autoGenerate = true) val id: Int = 0, val title: String, val description: String, val isPinned: Boolean = false )

4- Create DAO interface:


 @Dao
interface NoteDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(note: Note)

    @Update
    suspend fun update(note: Note)

    @Delete
    suspend fun delete(note: Note)

    @Query("SELECT * FROM notes ORDER BY isPinned DESC, id ASC")
    fun getAllNotes(): LiveData<List<Note>>
}

5- Create Room Database

    @Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
    abstract fun noteDao(): NoteDao

    companion object {
        @Volatile
        private var INSTANCE: NoteDatabase? = null

        fun getDatabase(context: Context): NoteDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    NoteDatabase::class.java,
                    "note_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

6- Create Repository Class

    class NoteRepository(private val noteDao: NoteDao) {
    val allNotes: LiveData<List<Note>> = noteDao.getAllNotes()

    suspend fun insert(note: Note) {
        noteDao.insert(note)
    }

    suspend fun update(note: Note) {
        noteDao.update(note)
    }

    suspend fun delete(note: Note) {
        noteDao.delete(note)
    }
}

7 - Create View Model 

    class NoteViewModel(application: Application) : AndroidViewModel(application) {
    private val repository: NoteRepository
    val allNotes: LiveData<List<Note>>

    init {
        val noteDao = NoteDatabase.getDatabase(application).noteDao()
        repository = NoteRepository(noteDao)
        allNotes = repository.allNotes
    }

    fun insert(note: Note) = viewModelScope.launch {
        repository.insert(note)
    }

    fun update(note: Note) = viewModelScope.launch {
        repository.update(note)
    }

    fun delete(note: Note) = viewModelScope.launch {
        repository.delete(note)
    }
}

8- Create an Adapter Class Using Kotlin

      class NoteAdapter(private val listener: OnItemClickListener) : RecyclerView.Adapter<NoteAdapter.NoteViewHolder>() {
    private var notes: List<Note> = emptyList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_note, parent, false)
        return NoteViewHolder(view)
    }

    override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
        val note = notes[position]
        holder.bind(note)
    }

    override fun getItemCount(): Int {
        return notes.size
    }

    fun setNotes(notes: List<Note>) {
        this.notes = notes
        notifyDataSetChanged()
    }

    inner class NoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        private val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
        private val descriptionTextView: TextView = itemView.findViewById(R.id.descriptionTextView)
        private val pinImageView: ImageView = itemView.findViewById(R.id.pinImageView)

        init {
            itemView.setOnClickListener(this)
            pinImageView.setOnClickListener {
                listener.onPinClick(notes[adapterPosition])
            }
        }

        fun bind(note: Note) {
            titleTextView.text = note.title
            descriptionTextView.text = note.description
            pinImageView.setImageResource(if (note.isPinned) R.drawable.ic_pinned else R.drawable.ic_unpinned)
        }

        override fun onClick(v: View?) {
            listener.onItemClick(notes[adapterPosition])
        }
    }

    interface OnItemClickListener {
        fun onItemClick(note: Note)
        fun onPinClick(note: Note)
    }
}

9 Create Layout -:

  • create_main_activty.xml
           <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/searchEditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Search notes"
        android:padding="16dp" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/searchEditText"
        android:padding="16dp" />
    
    <Button
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_margin="16dp"
        android:background="?attr/colorPrimary"
        android:text="Add" />
</RelativeLayout>
  • item_notes.xml
         <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    app:cardCornerRadius="8dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <TextView
            android:id="@+id/titleTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/descriptionTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/titleTextView"
            android:textSize="14sp" />

        <ImageView
            android:id="@+id/pinImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:src="@drawable/ic_unpinned" />
    </RelativeLayout>
</androidx.cardview.widget.CardView>
       
  •      activity_insert.xml and activity_update.xml
           These layouts will be similar and include EditTexts for title and description and a Button to save the note.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".InsertActivity"> <EditText android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:padding="16dp" /> <EditText android:id="@+id/descriptionEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/titleEditText" android:hint="Description" android:padding="16dp" /> <Button android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/descriptionEditText" android:layout_centerHorizontal="true" android:layout_marginTop="16dp" android:text="Save" /> </RelativeLayout>

10- Implement Activities 

  • Main Activity
         class MainActivity : AppCompatActivity(), NoteAdapter.OnItemClickListener {
    private lateinit var noteViewModel: NoteViewModel
    private lateinit var adapter: NoteAdapter

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

        adapter = NoteAdapter(this)
        val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)

        noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
        noteViewModel.allNotes.observe(this, Observer { notes ->
            notes?.let { adapter.setNotes(it) }
        })

        val searchEditText: EditText = findViewById(R.id.searchEditText)
        searchEditText.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                val query = s.toString().trim()
                adapter.setNotes(noteViewModel.allNotes.value?.filter {
                    it.title.contains(query, ignoreCase = true) || it.description.contains(query, ignoreCase = true)
                } ?: emptyList())
            }
            override fun afterTextChanged(s: Editable?) {}
        })

        findViewById<Button>(R.id.fab).setOnClickListener {
            startActivity(Intent(this, InsertActivity::class.java))
        }
    }

    override fun onItemClick(note: Note) {
        val intent = Intent(this, UpdateActivity::class.java)
        intent.putExtra("note_id", note.id)
        startActivity(intent)
    }

    override fun onPinClick(note: Note) {
        noteViewModel.update(note.copy(isPinned = !note.isPinned))
    }
}
  • Insert Activity
      class InsertActivity : AppCompatActivity() {
    private lateinit var noteViewModel: NoteViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_insert)

        noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)

        findViewById<Button>(R.id.saveButton).setOnClickListener {
            val title = findViewById<EditText>(R.id.titleEditText).text.toString()
            val description = findViewById<EditText>(R.id.descriptionEditText).text.toString()

            if (title.isNotEmpty() && description.isNotEmpty()) {
                noteViewModel.insert(Note(title = title, description = description))
                finish()
            } else {
                Toast.makeText(this, "Please enter both title and description", Toast.LENGTH_SHORT).show()
            }
        }
    }
}
  • Update Activity
        class UpdateActivity : AppCompatActivity() {
    private lateinit var noteViewModel: NoteViewModel
    private var noteId: Int = -1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_update)

        noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
        noteId = intent.getIntExtra("note_id", -1)

        val titleEditText: EditText = findViewById(R.id.titleEditText)
        val descriptionEditText: EditText = findViewById(R.id.descriptionEditText)

        if (noteId != -1) {
            noteViewModel.allNotes.observe(this, Observer { notes ->
                val note = notes.find { it.id == noteId }
                note?.let {
                    titleEditText.setText(it.title)
                    descriptionEditText.setText(it.description)
                }
            })
        }

        findViewById<Button>(R.id.saveButton).setOnClickListener {
            val title = titleEditText.text.toString()
            val description = descriptionEditText.text.toString()

            if (title.isNotEmpty() && description.isNotEmpty()) {
                noteViewModel.update(Note(id = noteId, title = title, description = description))
                finish()
            } else {
                Toast.makeText(this, "Please enter both title and description", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

This setup should give you a basic TODO app with pinning, searching, inserting, updating, and deleting notes using Room, ViewModel, LiveData, and RecyclerView in Kotlin. Adjust the code and add more features as needed.


Comments