Intro to Android Development
  • Welcome
  • Syllabus
  • Hack Challenge
  • Resources
    • Lecture Videos
    • Ed Discussion
    • Git & GitHub Help/How-To
    • Setting up Android Studio
    • Starting an Android Studio Project & Making an Emulator
    • Importing, Exporting, & Submitting Your Projects to CMS
  • SP25 Course Material
    • Week 1 | Course Logistics, Kotlin, & Basic UI
      • Relevant Links
      • Demo/Lecture: Eatery Card
      • A0: Eatery Card (Follow-Along)
    • Week 2 | States, Components, LazyColumn
      • Relevant Links
      • Demo: Todo List
      • A2: Shopping List
    • Week 3 | Navigation & Animations
      • Relevant Links
      • Demo: Onboarding
      • A3: Stock Trading (RobbingGood)
    • Week 4 | MVVM and Flows
      • Relevant Links
      • Demo: Eatery Card 2
      • A4: Chat of a Lifetime
    • Week 5 | Dumb Components & UIEvents
      • Relevant Links
      • Demo: Music Player
      • A5: Rate My Vibe
    • Week 6 | Coroutines, Networking, JSON
      • Relevant Links
      • Demo: Retrofit
      • A6: You Should Even Lift, Bro.
  • Bonus Week | Android Job Search
    • Relevant Links
    • Android Technical Interview Question!
  • Textbook
    • 1. Introduction to the Editor and Views
      • 1.1 Introduction to the Editor
      • 1.2 SDK Management
      • 1.3 Kotlin Overview
      • 1.4 Views
      • 1.5 Android Studio Project Demo + Understanding The Editor
    • 2. Jetpack Compose
      • 2.1 Introduction
      • 2.2 Layouts
      • 2.3 Modifiers
      • 2.4 Animations
      • 2.5 Lazy Lists
      • 2.6 Reactive UI
    • 3. Intents and Manifest
      • 3.1 Activities
      • 3.2 Implicit Intents
      • 3.3 Explicit Intents
      • 3.4 Manifest
      • 3.5 Permissions
      • 3.6 Summary
    • 4. Navigation
      • 4.1 Types of Navigation
      • 4.2 Implementation of the Bottom Navigation Bar
    • 5. Data and Persistent Storage
      • 5.1 Singleton Classes
      • 5.2 Shared Preferences
      • 5.3 Rooms
      • 5.4 Entities
      • 5.5 Data Access Objects
      • 5.6 Databases
    • 5.5 Concurrency
      • 5.5.1 Coroutines
      • 5.5.2 Implementation of Coroutines
      • 5.5.3 Coroutines with Networking Calls
    • 6. Networking and 3rd Party libraries
      • 6.1 HTTP Overview
      • 6.2 3rd Party Libraries
      • 6.3 JSON and Moshi
      • 6.4 Retrofit
      • 6.5 Summary
    • 7. MVVM Design Pattern
      • 7.1 Key Idea
      • 7.2 Implementation Ideas
    • 8. Flows
    • 9. The Art and Ontology of Software
    • 10. 🔥 Firebase
      • 10.1 Setting up Firebase
      • 10.2 Authentication
      • 10.3 Analytics
      • 10.4 Messaging
      • 10.5 Firestore
  • Additional Topics
    • Git and GitHub
    • Exporting to APK
  • Archive
    • Archived Native Android Textbook Pages
      • 1. Layouts and More Views
        • 1.1 File Structure and File Types
        • 1.2 Resource Files
        • 1.3 Button and Input Control
        • 1.4 ViewGroups
        • 1.5 Summary + A Note On Chapter 2 Topics
      • 2. RecyclerViews
        • 2.1 RecyclerViews
        • 2.2 RecyclerView Performance
        • 2.3 Implementation of a Recycler View
        • 2.4 Implementation with Input Controls
        • 2.5 Filtering RecyclerViews
        • 2.6 Recyclerview Demo
      • 3. ListViews and Searching
        • 3.1 ListView vs. RecyclerView
        • 3.2 ListView Performance
        • 3.3 Implementation of a ListView
        • 3.4 Searching in a List View
      • 4. Fragments
        • 4.1 What are Fragments?
        • 4.2 Lifecycle of a Fragment
        • 4.3 Integrating a Fragment into an Activity
        • 4.4 Sharing Data Between Fragments
        • 4.5 Fragment Slide Shows
      • 5. OkHttp
      • 6. Activity Lifecycle
      • 7. Implementation of Tab Layout
    • Fall 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 1.5: Beauty of Kotlin
      • Lecture 2 & HW 2: Modifiers, Lazylists and Reactive UI
      • Lecture 3 & HW 3: Animations, Intents and Manifest
      • Lecture 4 & HW 4: Coroutines & Navigation
      • Lecture 5 & HW 5: Persistent Storage, Networking, and JSON Parsing
      • Lecture 6 & HW 6: MVVM, Flows
      • Bonus Lectures & Bonus HW
      • Bonus Lecture: Industry Practice
    • Spring 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 4 & HW 4: LazyLists
      • Lecture 6 & HW 6: Networking, Data, and Persistent Storage
    • Spring 2020 Course Material
      • Week 1: Intro to the Editor
      • Week 2: Views and Layouts
      • Week 3: Intent and Manifest
      • Week 4: ListView and RecyclerView
      • Week 5: Fragments
      • Week 6: Networking
    • Spring 2021 Lecture & HW 8: Networking & 3rd Party APIs
    • HackOurCampus Workshop
Powered by GitBook
On this page
  • Step 1: Set Up Your TodoScreen.kt File
  • Step 2: "My Todo List"
  • Step 3: TextField
  • Step 4: Button
  • Step 5: TodoCard
  • Step 6: LazyColumn
  • Congrats, you've completed the demo! :)

Was this helpful?

  1. SP25 Course Material
  2. Week 2 | States, Components, LazyColumn

Demo: Todo List

Some more practice with components and states!

PreviousRelevant LinksNextA2: Shopping List

Last updated 1 month ago

Was this helpful?

In this demo, we'll build a simple todo list app with functionality to add new todos and display them in a scrolling list using components.

You'll start with an Empty Activity Project in Android Studio (see last week's demo for a refresher on how to do this)

Let's break this screen down into its individual components to help you get started:


Step 1: Set Up Your TodoScreen.kt File

Like the past couple of demos, you'll want to start by creating a file for your your screen. Let's call this one TodoScreen.kt

We'll also be using a custom component within our screen called TodoCard, which we'll go ahead and define in this file along with the TodoScreen composable.

@Composable
fun TodoScreen(){
    //...
}

@Composable
fun TodoCard(){
    //...
}

The TodoScreen is made up of multiple components that are visually "stacked" on top of each other, so we want to wrap everything in a Column component

To achieve the correct alignment of the contents of the Column, make use of the the modifier, horizontalAlignment, and verticalArrangement arguments.


Step 2: "My Todo List"

To start, make the title of the screen with font size 36.dp

Add a Spacer component with height 30.dp after this to make the screen more visually appealing


Step 3: TextField

This is where you'll be able to enter a new todo to be added to the list below.

To start, TextFields are valuable since they allow users to input some data that can then be stored, manipulated, and/or displayed later. Since the TextField value can be manipulated, let's use a MutableState to represent it.

var newTodo by remember{ mutableStateOf("") }

Like most components, TextField has a lot of different arguments possible. You'll usually only need to use four of them: modifier, placeholder, value, and onValueChange.

  • If you roll over TextField to look at all of the arguments, you'll notice that there's some arguments with a type that looks like some variant of this () -> Unit. This means that you'll need to pass in a function.

    • Functions passed into arguments can either be defined elsewhere and called inline, or they can be defined inline within {}.

  • This can be a little tricky, so give it a try yourself and check the answer when you need to!

TextField Arguments
TextField(
    modifier = Modifier.fillMaxWidth(),
    placeholder = { Text("new todo") },
    value = newTodo,
    onValueChange = { newText ->
        newTodo = newText
    }
)

Please ask if you have any questions about this!

Now when you build your code, you should be able to type in the TextField in the emulator!


Step 4: Button

When the Add Todo button is pressed, we want the current value of the TextField to be stored somewhere. For that we'll use the following:

val todoList by remember{ mutableStateListOf<String>() }

Here we use a val rather than a var since the List itself is mutable. When we update the list, we aren't defining a new one, just updating the existing one.

Button Syntax
Button(
    modifier,
    onClick = { }//what happens when the button is clicked 
){
    //the visual contents of your button
    //typically a Text component with the label that you want to use for the button.
}
  • In the onClick argument of your Button, add the current value of the TextField to the todoList.

    • hint: if you want to see the possible functions on todoList, type todoList dot and look over the list that comes up.

  • We also want to clear the TextField after the current value is stored in the list. To do this, we can also set newTodo = "" in the onClick argument.

    • hint: functions within the argument's curly braces need to be separated using a semicolon.

  • Label the Button using a Text composable within the Button component's curly braces.

Now when you build the app, the TextField should reset to display the placeholder when you press the button.

  • Behind the scenes, the TextField value is being stored in todoList before it's cleared, but we aren't making any UI updates when that happens so we can't see it just yet!

Add another Spacer with height 30.dp here!


Step 5: TodoCard

Todos will be displayed as a LazyColumn of TodoCards. Let's build that now!

Each card is going to be a stylized Row component. We'll want to use the modifier, padding, and background arguments.

  • Note that the order in which you call Modifiers affects the appearance of the card. Pay attention to the order of the .padding() and .background() modifiers and see if you can figure out what's happening there.

Additional Specs:

  • Add padding so that when the TodoCards are eventually displayed in a LazyColumn there's some vertical space between each card.

  • The example card is LightGray, one of the Color class's default colors

  • The TodoCard has corners with "roundness" of 12.dp

  • Use 20.dp of padding between the Text and the edges of the card.

Write an @Preview composable for TodoCard and check that it matches the sample above!

Step 6: LazyColumn

Now that we have our TodoCard, let's use them to display our todoList with a LazyColumn.

Make a LazyColumn component in the TodoScreen that:

  • Displays TodoCards with data from todoList

  • Has height 200.dp

LazyColumn Syntax
LazyColumn(){
    items(some-list){
        some-composable(it) 
    }
}
//'it' is an implicitly declared name for a single-parameter lambda expression.
//it pretty much acts as each element of some-list so you don't need to iterate through some-list manually

You might need to do two imports on the items() code. Hover over any red lines to see if you missed an import!

hint: Use the verticalAlignment argument with Alignment.spacedBy() in the LazyColumn to make space between each TodoCard when they're displayed.

Run your app again. Now, when you type in a todo and hit the Add Todo button, you should see it appear below in order below the Button.

When you add enough todos, you'll be able to scroll through the LazyColumn!

Congrats, you've completed the demo! :)