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

Was this helpful?

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

A2: Shopping List

Keeping track of expenses!

PreviousDemo: Todo ListNextWeek 3 | Navigation & Animations

Last updated 2 months ago

Was this helpful?

As this is a smaller-scope assignment, there is no release code. Simply start from an empty Compose activity / new project.

For our second (and first graded) assignment, we'll be making a simple app to keep track of some expenses!

We'll need to leverage states and make some components to, in the end, use a LazyColumn to show our expenses in the following UI:

Requirements:

(expand each file below to see your requirements!)

ExpenseRow.kt (3pt)

We'll start off by making a very simple UI for an expense row in our app!

In general, try to match this UI:

  1. The expense row should have a title section for the expense title.

  2. Below, the expense row should have a time section for the date/time the expense occurred.

  3. To the far right, the expense row should have the expense.

    1. This text must be bold.

    2. If the amount is positive, it should be green. Otherwise, red.

Hints:

  • Although not required, we highly recommend making a @Preview function in this file so you can see your expense row as you are developing!

  • If you are unsure of how to specifically match this UI, look at Modifiers and the input arguments to components like Text , Row, and Column.

  • Use the following logical code to convert a amountnumber (Float) to a nice 2-digit-formatted string:

    // Format 2 digits after the decimal
    val formatted = "%.2f".format(abs(amount))
    val amountString = if (amount < 0) {
        "-$$formatted"
    } else {
        "+$$formatted"
    }
    // use amountString...
ExpenseHeader.kt (4pt)

In this file, you'll make the app's top header which relies on user input to allow the user to input new expenses into the app.

In general, try to match this UI:

  1. Add a TextField that takes in the name of the expense, allowing the user to type with any characters.

    1. The placeholder of this should read "Expense Name"

  2. Add a TextFieldthat takes in the cost of the expense.

    1. The placeholder of this should read something similar to the above.

  3. Add a Button that, when pressed, fires an onClick or similar function passed into the component to tell the parent component that a new entry was submitted with the corresponding Stringname and Float amount.

    1. When you call the onClick, you should also afterwards clear the input of both text fields.

    2. It's okay if your code only works if the user has actually typed in a valid amount.

  4. Add a nice title text to the top of it all!

Hints:

  • If you make an @Preview to test out your component, you can actually RUN the preview and test typing into your component to see if it works! Just hit this button:

Then, you can type into the text fields and even hit submit! (You won't see an OS keyboard; just type in with your computer keyboard. Make sure then to only type numbers into the other text field.)

MainScreen.kt (5pt)

iIn this file, you'll assemble everything together to make the app's screen!

  1. Make a new file called MainScreen.kt with a corresponding @Composable.

  2. Arrange the UI with a LazyColumn so that the header is on top, and several expense rows render underneath.

  3. Whenever the user enters a new expense and clicks "Create", a new expense row should appear in the LazyColumn.

    1. This expense should have the same title, expense, and (some form) of representing the (system) time at which the expense was created.

Hints:

  • You'll need a state to represent the list of expenses. When you update this state, the lazy column will auto-render new rows (Recomposition Lifecycle!)

  • Use callback functions from the ExpenseHeader that will fire whenever the user enters/submits a new expense.

  • For the system time, feel free to ask ChatGPT conceptual questions as to how to get the system time and convert it into a date-time readable format! Here's one possible way to do that:

// Get the current time as a number.
val currentTimeMillis = System.currentTimeMillis()

// Format it into a readable string.
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
    .withZone(ZoneId.systemDefault())
val formattedTime = formatter.format(Instant.ofEpochMilli(currentTimeMillis))
  • You'll probably want to make some data classthat represents an Entry. This data class would be called something like Expense and could have fields such as title, dateTime, and cost.

    • Then you can make a State that is a list of these expenses!

Make sure to also change the proper things in MainActivity.kt to actually get your screen to show when you run your emulator! Once finished, your app should look something like this:

When you're done, export your project through Android Studio and upload your ZIP to CMS! Congrats on finishing A2!

11MB
a2-soln-demo.webm
Solution Demo Video!
(An @Preview of) the final product!
Exporting with File -> Export -> Export to Zip File...