Build a Tip Calculator Android App
Build an Android tip calculator app using Jetpack Compose and Claude Code.
Introduction
30 Second Summary
Splitting a dinner bill shouldn't require a math degree. Yet every time the check arrives, someone pulls out their phone calculator and squints at the screen trying to figure out the tip.
In this project, you will build a Tip Calculator Android app using Claude Code as your AI coding assistant. You'll go from zero to a polished app running on an Android emulator, learning how to describe what you want and let AI generate the code for you.
What You'll Build
A Tip Calculator app built with Kotlin and Jetpack Compose that calculates tips and totals in real time as users enter a bill amount and select a tip percentage.
By the end of this project, you'll have:
- A complete Android Studio project with an interactive single-screen app running on an emulator.
- A practiced workflow for using Claude Code to generate, review, and iterate on Android code.
- A CLAUDE.md file that gives Claude Code project context every time you start a session.
- Secret Mission: Add a bill-splitting feature that divides the total among multiple people.
Are there any prerequisites?
None. This project includes full setup instructions for every tool you need. You don't need any prior experience with Android development, Kotlin, or AI coding assistants.
Before We Start
Before We Start...
Install Android Studio
Before you can build an Android app, you need a development environment. Android Studio is the official IDE for building Android apps. It comes bundled with a code editor, build tools, and an emulator for testing your app on a virtual phone.
In this step, you'll download and install Android Studio, confirm the Android SDK is ready, and set up an Android Emulator so you have a virtual phone to run your app on.
In this step, get ready to:
- Install Android Studio Panda 4.
- Confirm the Android SDK is installed.
- Set up an Android Emulator with a virtual device.
Download and install Android Studio
Android Studio is a large application (around 1.5 GB) that includes everything you need for Android development. The download page automatically detects your operating system and offers the correct installer.
- Check if you already have Android Studio installed by searching for it on your computer.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Android Studio and check whether it appears in the results.
✔️ I have Android Studio Panda 4 or newer
You're all set. Skip ahead to the next substep where you confirm the Android SDK.
Check your version
On macOS, click Android Studio in the menu bar, then About Android Studio. On Windows, click Help then About. You should see 2025.3.4 or higher in the version string.
ⓧ I have an older version of Android Studio
You'll need to update to the latest version. The installer will replace your current version.
- Close Android Studio if it's currently open.
- Open your browser and go to the Android Studio download page:
https://developer.android.com/studio
- Click Download Android Studio.
- Read and accept the License Agreement by checking the checkbox at the bottom of the page.
- Click Download Android Studio again to start the download.
macOS
- Open the downloaded .dmg file.
- Drag the Android Studio icon into the Applications folder.
- Launch Android Studio from your Applications folder.
- The Setup Wizard will appear. Accept the defaults and click Next through each screen until it finishes.
What does the Setup Wizard do?
The Setup Wizard downloads the Android SDK and essential components. This can take 5-10 minutes depending on your internet speed. Let it finish completely before moving on.
Windows
- Double-click the downloaded .exe file.
- If a User Account Control dialog asks to allow changes, click Yes.
- Click Next to start the installation.
- Accept the default installation settings for all steps.
- Click Finish when the installation is done to launch Android Studio.
- The Setup Wizard will appear. Accept the defaults and click Next through each screen until it finishes.
What does the Setup Wizard do?
The Setup Wizard downloads the Android SDK and essential components. This can take 5-10 minutes depending on your internet speed. You may see additional Windows Security alerts for adb.exe. Click Allow Access to continue.
ⓧ I don't have Android Studio
No problem. Let's install it from scratch.
- Open your browser and go to the Android Studio download page:
https://developer.android.com/studio
- Click Download Android Studio.
- Read and accept the License Agreement by checking the checkbox at the bottom of the page.
- Click Download Android Studio again to start the download.
- Save the file to a location you can easily find, such as your Downloads folder.
macOS
- Open the downloaded .dmg file.
- Drag the Android Studio icon into the Applications folder.
- Launch Android Studio from your Applications folder.
- The Setup Wizard will appear. Accept the defaults and click Next through each screen until it finishes.
What does the Setup Wizard do?
The Setup Wizard downloads the Android SDK and essential components. This can take 5-10 minutes depending on your internet speed. Let it finish completely before moving on.
Windows
- Double-click the downloaded .exe file.
- If a User Account Control dialog asks to allow changes, click Yes.
- Click Next to start the installation.
- Accept the default installation settings for all steps.
- Click Finish when the installation is done to launch Android Studio.
- The Setup Wizard will appear. Accept the defaults and click Next through each screen until it finishes.
What does the Setup Wizard do?
The Setup Wizard downloads the Android SDK and essential components. This can take 5-10 minutes depending on your internet speed. You may see additional Windows Security alerts for adb.exe. Click Allow Access to continue.
What are the system requirements?
Android Studio with the emulator needs at least 16 GB of RAM and 16 GB of free disk space. On macOS, you need macOS 12 or later with an Apple M1 chip or 6th-gen Intel Core. On Windows, you need 64-bit Windows 10 or later.
Setup Wizard stuck or failing?
The Setup Wizard requires a stable internet connection to download SDK components. If it fails, check your connection and try again. On macOS, make sure you dragged Android Studio into Applications before launching it.
help me troubleshoot Android Studio installation issues
Verify the Android SDK is installed
After the Setup Wizard finishes, Android Studio opens to the Welcome screen. Before moving on, you'll confirm the Android SDK was installed correctly.
- Confirm you see the Welcome to Android Studio screen with options like New Project and Open.
✔️ I see the Welcome to Android Studio screen
The installation was successful. Now let's confirm the SDK is in place.
- On the Welcome screen, click Customize in the left sidebar (or go to Android Studio > Settings on macOS, or File > Settings on Windows).
- Navigate to Languages & Frameworks > Android SDK.
- Confirm you see an Android SDK Location path filled in (it should not be empty or show an error).
- Under the SDK Platforms tab, confirm at least one platform is checked and installed.
What is the Android SDK?
The Android SDK (Software Development Kit) contains the tools, libraries, and APIs needed to compile and run your app. The Setup Wizard installs it automatically, so you just need to confirm it's there.
ⓧ Android Studio won't open or I see an error
If Android Studio fails to launch or shows an error, try these fixes.
- On macOS, right-click the Android Studio icon in Applications and select Open (this bypasses Gatekeeper security warnings on first launch).
- On Windows, right-click the Android Studio shortcut and select Run as administrator.
- If you see a Java or JDK error, the Setup Wizard may not have completed. Re-run Android Studio and let the wizard finish.
help me fix Android Studio not launching
Set up the Android Emulator
The Android Emulator creates a virtual phone on your computer so you can test your app without needing a physical device. You'll create a virtual device that mimics a Pixel 8 running the latest Android version.
- In Android Studio, click More Actions (or ...) on the Welcome screen, then select Virtual Device Manager.
- Click Create Virtual Device.
- In the device list, select Pixel 8 (under the Phone category) and click Next.
- On the System Image screen, select the latest image with API level 35. If it shows a Download link next to it, click that first and wait for the download to finish.
- Click Next, then click Finish to create the virtual device.
Why Pixel 8 and API 35?
The Pixel 8 is a modern phone shape with standard dimensions. API 35 is the latest stable Android version, ensuring your app runs on the newest features. You can always create additional devices later for testing on different screen sizes.
- Back in the Device Manager, click the Play button (triangle icon) next to your new Pixel 8 device to start the emulator.
- Wait for the virtual phone to boot. You should see an Android home screen appear in the emulator window.
First boot takes a while
The emulator's first boot can take 1-2 minutes as it sets up the virtual phone. Subsequent launches will be faster. If your computer feels slow, close other heavy applications while the emulator runs.
✔️ I see the Android home screen in the emulator
Your emulator is working. You now have a virtual phone ready to run your Tip Calculator app.
ⓧ The emulator won't start or shows a black screen
- Make sure you have at least 16 GB of RAM. The emulator needs significant memory to run alongside Android Studio.
- On Windows, ensure virtualization (Intel VT-x or AMD-V) is enabled in your BIOS settings.
- Try closing the emulator, going back to Device Manager, and clicking the Play button again.
- If you see a GPU-related error, go to the device's edit settings (pencil icon) and under Emulated Performance, change Graphics to Software.
help me fix my Android Emulator not starting
Your development environment is fully set up. Next, you'll install Claude Code and create your Android project.
Install Claude Code and Set Up the Project
Your development environment is ready to go. Now you need two more things: an AI coding assistant to help write your app, and an actual Android project for it to work on.
In this step, you'll install Claude Code (an AI tool that runs in your terminal and writes code for you), create your TipCalculator project in Android Studio, and set up a CLAUDE.md file that teaches Claude Code about your project.
In this step, get ready to:
- Install and authenticate Claude Code.
- Create the TipCalculator project in Android Studio.
- Create a CLAUDE.md file to give Claude Code project context.
Install Claude Code
Claude Code is an AI-powered coding assistant that runs entirely in your terminal. You describe what you want in plain English, and it writes the code for you.
What is Claude Code?
Claude Code reads your entire codebase, edits files, and runs commands. You'll use it as a pair programmer throughout this project.
It requires a Claude Pro ($20/month) or Max subscription. The free Claude.ai plan does not include Claude Code access.
- Press Cmd+Space to open Spotlight search.
- Type Terminal and press Enter to open it.
- Install Claude Code by running this command:
curl -fsSL https://claude.ai/install.sh | bash
What does this command do?
This downloads and runs the Claude Code installer from claude.ai. You'll see text scrolling as it works. When it finishes, you'll see a success message.
Prefer Homebrew?
If you use Homebrew, you can install with brew install --cask claude-code instead.
After the installer finishes, verify the installation worked.
- Start Claude Code by running:
claude
✔️ A browser window opened for login
Claude Code is installed correctly. On first launch, it opens a browser window for you to log in.
- Sign in with your Claude Pro or Max account in the browser.
- Once authenticated, return to your terminal. You should see the Claude Code welcome screen.
Browser not opening?
If the browser doesn't open automatically, press c in the terminal to copy the login URL to your clipboard. Then paste it into your browser manually.
ⓧ Command not found
The installer may not have added Claude Code to your PATH. Try these fixes:
- Close your terminal completely and reopen it. Then run claude again.
- If that still doesn't work, confirm your macOS version is 13.0 or later by clicking the Apple menu and selecting About This Mac.
- Try reinstalling with the Homebrew method: brew install --cask claude-code.
- Once you see the Claude Code welcome screen, type exit and press Enter to close the session for now.
Why exit Claude Code?
You've confirmed it works. You'll relaunch Claude Code from inside your project directory in a later substep, so it has the right context.
Create the TipCalculator project in Android Studio
You need an Android project for Claude Code to work with. The Empty Activity template creates a minimal, Jetpack Compose-ready project with everything pre-configured.
- Switch back to Android Studio. You should still see the Welcome screen.
- Click New Project.
- In the template list, select Empty Activity.
- Click Next.
Why Empty Activity?
The Empty Activity template includes Compose dependencies and Material Design setup out of the box. It creates a clean starting point with no unnecessary boilerplate.
Now configure your project details.
- In the Name field, enter TipCalculator.
- In the Package name field, enter com.example.tipcalculator.
- Confirm the Language is set to Kotlin. This is the only option for Compose projects.
- Set the Minimum SDK to API 24 ("Android 7.0 Nougat").
- Leave all other settings as defaults.
- Click Finish.
Android Studio creates your project and begins syncing Gradle dependencies. This downloads everything your project needs and may take a few minutes the first time.
- Wait for the Gradle sync to complete. You'll see a "BUILD SUCCESSFUL" message in the Build panel at the bottom, or the progress bar at the bottom of the window will disappear.
Gradle sync taking forever?
The first sync downloads many dependencies and can take 3-5 minutes on a slower connection. If it fails, check your internet connection and try again by clicking File then Sync Project with Gradle Files.
help me fix my Gradle sync
Set up Claude Code in your project
Now you'll launch Claude Code from inside your project directory. This lets Claude Code see all your project files and understand its structure.
A CLAUDE.md file is a markdown file you add to your project root that Claude Code reads at the start of every session. It tells Claude Code your coding standards, tech stack, and conventions.
- Switch back to your Terminal window.
- Navigate to your project directory by running this command:
cd ~/AndroidStudioProjects/TipCalculator
- Start a Claude Code session by running:
claude
You should see the Claude Code welcome screen. Claude Code is now running in your project directory and can see all your files.
- Ask Claude Code to create your CLAUDE.md file. Type the following message and press Enter:
Create a CLAUDE.md file for this Android project. It should note that we use Kotlin with Jetpack Compose, Material 3, and that this is a Tip Calculator app. Include sections for Overview, Tech Stack (Language: Kotlin, UI Framework: Jetpack Compose with Material 3, Build System: Gradle with Kotlin DSL, Minimum SDK: API 24 Android 7.0), and Conventions (Use Jetpack Compose for all UI with no XML layouts, Follow Material 3 design guidelines, Keep all UI in composable functions, Use remember and mutableStateOf for state management, Format currency values using NumberFormat.getCurrencyInstance()).
What does this prompt do?
You're telling Claude Code exactly what to put in the file. Claude Code will create CLAUDE.md in your project root with all the details you specified. It may ask for permission to create the file.
If Claude Code asks for permission to write the file, approve it.
- After Claude Code creates the file, verify it exists by running this in the Claude Code session:
Can you show me the contents of CLAUDE.md?
Claude Code should display the file contents. Verify it includes sections for Overview, Tech Stack, and Conventions.
✔️ Awesome, I've got everything!
Great. Double check that your CLAUDE.md includes all three sections and mentions Kotlin, Jetpack Compose, Material 3, and the project conventions.
ⓧ I'd like to double check the full code
Your CLAUDE.md file should look like this:
# TipCalculator Project
## Overview
This is a Tip Calculator Android app built with Kotlin and Jetpack Compose.
## Tech Stack
- Language: Kotlin
- UI Framework: Jetpack Compose with Material 3
- Build System: Gradle with Kotlin DSL
- Minimum SDK: API 24 (Android 7.0)
## Conventions
- Use Jetpack Compose for all UI (no XML layouts)
- Follow Material 3 design guidelines
- Keep all UI in composable functions
- Use `remember` and `mutableStateOf` for state management
- Format currency values using `NumberFormat.getCurrencyInstance()`
If your file is missing any sections or has different content, ask Claude Code to update it. For example: "Update CLAUDE.md to match this structure" and paste the content above.
Claude Code didn't create the file?
Make sure you're running claude from inside the ~/AndroidStudioProjects/TipCalculator directory. If you started it from a different folder, type exit to quit, then cd ~/AndroidStudioProjects/TipCalculator and run claude again.
help me troubleshoot Claude Code not creating files in my project
Your project is set up and Claude Code knows your conventions. Next up, you'll use Claude Code to build the entire Tip Calculator UI in one conversation.
Build the Tip Calculator UI
Your project is ready and Claude Code already knows about your app's conventions through the CLAUDE.md file. Now it's time to build the actual Tip Calculator interface.
You'll use Claude Code as a pair programmer to generate the entire UI in a single prompt. Claude Code reads your project files, understands the structure, and writes production-ready Kotlin code for you.
In this step, get ready to:
- Prompt Claude Code to generate the Tip Calculator UI.
- Run the app on the Android emulator.
- Test the tip calculations with real numbers.
Prompt Claude Code to generate the UI
Instead of writing hundreds of lines of Jetpack Compose code by hand, you'll describe what you want and let Claude Code handle the implementation. The more specific your prompt, the better the result.
- Switch back to your Claude Code session in Terminal.
- Type the following prompt and press Enter:
Replace the content of app/src/main/java/com/example/tipcalculator/MainActivity.kt with a Tip Calculator app using Jetpack Compose. It should have: a text field for bill amount, a row of tip percentage buttons (15%, 18%, 20%), and display the calculated tip amount and total. Use Material 3 styling.
What happens when you send this prompt?
Claude Code reads your CLAUDE.md file and project structure to understand the context. It then generates a complete MainActivity.kt file with all the Material 3 composables needed for the calculator.
Claude Code may include additional features beyond what you asked for (like input validation or a custom slider). This is normal. AI assistants often anticipate needs based on the project context.
- Review the generated code that Claude Code shows you.
- Look for these key elements: an OutlinedTextField for bill input, FilterChip components for tip percentages, and Text elements displaying the tip and total.
- Approve the changes when Claude Code asks for confirmation.
What is a composable function?
In Jetpack Compose, every piece of UI is built with functions annotated with @Composable. Instead of XML layout files, you describe your UI using Kotlin functions that automatically update when data changes.
The generated code wraps all the calculator UI inside a function called TipCalculatorScreen(). This is the single composable that holds everything the user sees.
- Verify the file was updated by checking that app/src/main/java/com/example/tipcalculator/MainActivity.kt now contains your Tip Calculator code.
Claude Code didn't generate the file?
Make sure you're running Claude Code from the TipCalculator project root directory (~/AndroidStudioProjects/TipCalculator). If you're in a different directory, Claude Code can't find the file to replace.
If Claude Code asks a clarifying question instead of generating code, answer it and let it proceed. Help me troubleshoot my Claude Code prompt
Run the app on the emulator
With the code generated, you need to build and deploy the app to see it in action. Android Studio compiles your Kotlin code and installs it on the emulator you set up earlier.
- Switch back to Android Studio.
- If you see a banner saying files have changed externally, click Reload or Sync to pick up Claude Code's changes.
- Click the green Run button (triangle icon) in the top toolbar, or press Ctrl+R (macOS) or Shift+F10 (Windows).
- Select your Pixel 8 emulator as the deployment target if prompted.
The build process takes 30-60 seconds the first time. You should see your Tip Calculator UI appear on the emulator with a bill amount field and tip percentage buttons.
Seeing build errors?
Build errors are common when AI generates code. Copy the full error message from Android Studio's Build panel at the bottom of the screen.
Switch back to your Claude Code session and paste the error. Ask Claude Code to fix it. It will read the error, identify the issue, and update the file. Then run the app again in Android Studio.
Help me fix my build error
Test the tip calculations
A working UI means nothing if the math is wrong. You'll test with a known bill amount to verify the calculations are correct.
- Tap the bill amount field on the emulator and type 50.00.
- Tap the 20% tip button.
- Confirm the tip amount shows $10.00 and the total shows $60.00.
- Try another combination: enter 75.00 as the bill and tap 15%.
- Confirm the tip shows $11.25 and the total shows $86.25.
Why these specific numbers?
Testing with known values lets you verify the formula: tip = bill x percentage / 100. For $50 at 20%, that's 50 x 0.20 = $10.00 tip, plus the original $50 = $60.00 total.
Testing with $75 at 15% catches rounding issues: 75 x 0.15 = $11.25. If either value is wrong, the calculation logic needs fixing.
Calculations are wrong?
If the tip or total values don't match, describe the problem to Claude Code. For example: "When I enter 50.00 and tap 20%, the tip shows $5.00 instead of $10.00. Fix the calculation."
Claude Code will identify whether the percentage math or display formatting is off and update the file. Run the app again to verify the fix.
Help me debug my tip calculations
✔️ Awesome, I've got everything!
Great. Make sure you've saved all your work and your app is running cleanly on the emulator.
ⓧ I'd like to double check the full code
Here's what your MainActivity.kt should look like. Your Claude Code output may differ slightly in formatting or variable names, but the core structure should match.
package com.example.tipcalculator
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.tipcalculator.ui.theme.TipCalculatorTheme
import java.text.NumberFormat
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TipCalculatorTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
TipCalculatorScreen()
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TipCalculatorScreen() {
var billAmount by remember { mutableStateOf("") }
var selectedTipPercent by remember { mutableIntStateOf(-1) }
var customTipPercent by remember { mutableFloatStateOf(18f) }
var isInputError by remember { mutableStateOf(false) }
val tipPercentOptions = listOf(15, 18, 20)
val activeTipPercent = if (selectedTipPercent >= 0) {
selectedTipPercent.toDouble()
} else {
customTipPercent.toDouble()
}
val billValue = billAmount.toDoubleOrNull() ?: 0.0
val tipAmount = billValue * activeTipPercent / 100.0
val totalAmount = billValue + tipAmount
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp)
.padding(top = 48.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = "Tip Calculator",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = billAmount,
onValueChange = { newValue ->
val regex = Regex("^\\d*\\.?\\d{0,2}$")
if (newValue.isEmpty() || regex.matches(newValue)) {
billAmount = newValue
isInputError = false
} else {
isInputError = true
}
},
label = { Text("Bill Amount") },
prefix = { Text("$") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
isError = isInputError,
supportingText = {
if (isInputError) {
Text("Enter a valid number (e.g., 42.50)")
}
},
singleLine = true,
modifier = Modifier.fillMaxWidth()
)
Text(
text = "Tip Percentage",
style = MaterialTheme.typography.titleSmall
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth()
) {
tipPercentOptions.forEach { percent ->
FilterChip(
selected = selectedTipPercent == percent,
onClick = {
selectedTipPercent = if (selectedTipPercent == percent) -1 else percent
},
label = { Text("$percent%") },
modifier = Modifier.weight(1f)
)
}
}
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Custom: ${customTipPercent.toInt()}%",
style = MaterialTheme.typography.bodyMedium
)
Slider(
value = customTipPercent,
onValueChange = {
customTipPercent = it
selectedTipPercent = -1
},
valueRange = 0f..30f,
steps = 29,
modifier = Modifier.fillMaxWidth()
)
}
HorizontalDivider()
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("Tip Amount:", style = MaterialTheme.typography.titleMedium)
Text(
text = NumberFormat.getCurrencyInstance().format(tipAmount),
style = MaterialTheme.typography.titleMedium
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("Total:", style = MaterialTheme.typography.headlineSmall)
Text(
text = NumberFormat.getCurrencyInstance().format(totalAmount),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.primary
)
}
Spacer(modifier = Modifier.height(8.dp))
OutlinedButton(
onClick = {
billAmount = ""
selectedTipPercent = -1
customTipPercent = 18f
isInputError = false
},
modifier = Modifier.fillMaxWidth()
) {
Text("Clear")
}
}
}
@Preview(showBackground = true)
@Composable
fun TipCalculatorScreenPreview() {
TipCalculatorTheme {
TipCalculatorScreen()
}
}
Your Tip Calculator is alive on the emulator and doing real math. Next up, you'll polish the app by adding a custom tip slider, stricter input validation, and a reset button.
Polish the App with Claude Code
You have a working Tip Calculator that handles the basics. Now it's time to make it feel like a real app.
In this step, you'll use Claude Code to add three professional-grade features: a custom tip slider for flexibility, input validation to prevent bad data, and a reset button for convenience.
In this step, get ready to:
- Add a custom tip percentage slider.
- Add input validation to the bill amount field.
- Add a Clear button to reset the calculator.
Add a custom tip slider
The preset buttons cover common tip amounts, but users should have finer control. A slider lets someone pick any tip percentage between 0% and 30%.
- Switch back to your Terminal where Claude Code is running in the TipCalculator project directory.
- Enter this prompt into Claude Code:
Add a custom tip percentage option with a slider that goes from 0% to 30%. Update the calculation to use the slider value when no preset button is selected. Add proper labels and spacing.
- Review the changes Claude Code proposes. You should see it adding a Slider composable and a label showing the current custom percentage.
- Approve the changes when prompted.
What did Claude Code generate?
Claude Code adds a custom tip slider section to your UI. Here's what the key parts look like:
- A customTipPercent state variable with a default of 18%.
- A Slider with a range of 0 to 30 and 29 discrete steps.
- Logic that uses the slider value when no preset button is selected (selectedTipPercent == -1).
- Run the app by clicking the green Run button in Android Studio (or pressing Ctrl+R).
- In the emulator, drag the slider left and right. The tip and total values should update in real time.
- Tap one of the preset buttons (15%, 18%, 20%). The slider should deactivate and the preset value should be used instead.
Slider not updating the total?
If the slider moves but the tip and total don't change, the calculation might still be using only the preset buttons. Go back to Claude Code and say: "The slider value isn't being used in the tip calculation when no preset button is selected. Fix it."
If you see a build error after approving the changes, copy the full error message and paste it into Claude Code. It will fix the issue.
Help me debug why my custom tip slider isn't working.
Add input validation
Right now the bill amount field accepts any text. A user could type letters or multiple decimal points, breaking the calculation. Input validation prevents bad data from entering the app.
- Enter this prompt into Claude Code:
Add validation so the bill amount field only accepts numbers and a single decimal point. Show an error message if the input is invalid. Also round the tip and total to 2 decimal places.
- Review the changes Claude Code proposes. You should see it updating the onValueChange handler with a regex pattern and adding error-state UI.
- Approve the changes when prompted.
How does the validation work?
Claude Code uses a regex pattern ^\d*\.?\d{0,2}$ to check each character the user types. This pattern only allows digits, an optional single decimal point, and at most two digits after the decimal.
If the input doesn't match, the field shows an error state with the message "Enter a valid number (e.g., 42.50)" and rejects the invalid character.
- Run the app again with the green Run button.
- Try typing letters into the bill amount field. The field should reject them and show an error message.
- Type a valid number like 50.00 and confirm the tip and total display as properly formatted currency (e.g., $9.00 and $59.00 at 18%).
Error message not showing?
If you can type invalid characters without seeing an error, the isError state might not be connected to the OutlinedTextField. Tell Claude Code: "The error state isn't showing on the bill amount field when I type invalid characters. Make sure isError and supportingText are wired up."
Help me fix my input validation.
Add a Clear button
After calculating a tip, users need a quick way to start over for their next meal. A reset button clears all inputs and returns the app to its default state.
- Enter this prompt into Claude Code:
Add a 'Clear' button that resets the bill amount, tip percentage selection, and calculated values back to their defaults.
- Review the changes. You should see an OutlinedButton that resets all state variables when clicked.
- Approve the changes when prompted.
What does the Clear button reset?
The Clear button's onClick handler resets four state variables:
- billAmount back to an empty string.
- selectedTipPercent back to -1 (no preset selected).
- customTipPercent back to 18f (the default slider position).
- isInputError back to false (clears any error state).
- Run the app one more time.
- Enter a bill amount (e.g., 75.00), select a tip percentage, and confirm the totals display.
- Tap the Clear button. The bill amount, tip selection, and totals should all reset to their defaults.
Clear button not resetting everything?
If tapping Clear doesn't reset the slider or the calculated values still show, tell Claude Code: "The Clear button isn't resetting customTipPercent or isInputError. Update the onClick to reset all four state variables."
Help me fix the Clear button in my Tip Calculator.
Your polished Tip Calculator should now have all three features working together. Test the full workflow:
- Enter 50.00 as the bill amount.
- Tap the 20% preset button. You should see Tip Amount: $10.00 and Total: $60.00.
- Drag the custom slider to 25%. The totals should update to $12.50 and $62.50.
- Tap Clear and confirm everything resets.
✔️ Awesome, I've got everything!
Great. Double check you've saved your file in Android Studio.
ⓧ I'd like to double check the full code
Here's the complete MainActivity.kt file for comparison:
package com.example.tipcalculator
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.tipcalculator.ui.theme.TipCalculatorTheme
import java.text.NumberFormat
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TipCalculatorTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
TipCalculatorScreen()
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TipCalculatorScreen() {
var billAmount by remember { mutableStateOf("") }
var selectedTipPercent by remember { mutableIntStateOf(-1) }
var customTipPercent by remember { mutableFloatStateOf(18f) }
var isInputError by remember { mutableStateOf(false) }
val tipPercentOptions = listOf(15, 18, 20)
val activeTipPercent = if (selectedTipPercent >= 0) {
selectedTipPercent.toDouble()
} else {
customTipPercent.toDouble()
}
val billValue = billAmount.toDoubleOrNull() ?: 0.0
val tipAmount = billValue * activeTipPercent / 100.0
val totalAmount = billValue + tipAmount
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp)
.padding(top = 48.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = "Tip Calculator",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = billAmount,
onValueChange = { newValue ->
val regex = Regex("^\\d*\\.?\\d{0,2}$")
if (newValue.isEmpty() || regex.matches(newValue)) {
billAmount = newValue
isInputError = false
} else {
isInputError = true
}
},
label = { Text("Bill Amount") },
prefix = { Text("$") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
isError = isInputError,
supportingText = {
if (isInputError) {
Text("Enter a valid number (e.g., 42.50)")
}
},
singleLine = true,
modifier = Modifier.fillMaxWidth()
)
Text(
text = "Tip Percentage",
style = MaterialTheme.typography.titleSmall
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth()
) {
tipPercentOptions.forEach { percent ->
FilterChip(
selected = selectedTipPercent == percent,
onClick = {
selectedTipPercent = if (selectedTipPercent == percent) -1 else percent
},
label = { Text("$percent%") },
modifier = Modifier.weight(1f)
)
}
}
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Custom: ${customTipPercent.toInt()}%",
style = MaterialTheme.typography.bodyMedium
)
Slider(
value = customTipPercent,
onValueChange = {
customTipPercent = it
selectedTipPercent = -1
},
valueRange = 0f..30f,
steps = 29,
modifier = Modifier.fillMaxWidth()
)
}
HorizontalDivider()
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("Tip Amount:", style = MaterialTheme.typography.titleMedium)
Text(
text = NumberFormat.getCurrencyInstance().format(tipAmount),
style = MaterialTheme.typography.titleMedium
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("Total:", style = MaterialTheme.typography.headlineSmall)
Text(
text = NumberFormat.getCurrencyInstance().format(totalAmount),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.primary
)
}
Spacer(modifier = Modifier.height(8.dp))
OutlinedButton(
onClick = {
billAmount = ""
selectedTipPercent = -1
customTipPercent = 18f
isInputError = false
},
modifier = Modifier.fillMaxWidth()
) {
Text("Clear")
}
}
}
@Preview(showBackground = true)
@Composable
fun TipCalculatorScreenPreview() {
TipCalculatorTheme {
TipCalculatorScreen()
}
}
Your Tip Calculator is fully polished with professional features. Next up, you'll take on a Secret Mission to add bill-splitting for group dinners.
Secret mission
Add Bill Splitting
Your Tip Calculator works great for solo diners. But what about group dinners where everyone wants to split the bill evenly? In this secret mission, you'll add a bill-splitting feature that divides the total among multiple people.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local machine. The only ongoing cost is your Claude Pro subscription ($20/month), which you manage through your Anthropic account settings.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- Android Studio (installed application and Android SDK).
- Android Emulator (Pixel 8 virtual device).
- Claude Code CLI (installed locally).
- TipCalculator project folder at ~/AndroidStudioProjects/TipCalculator.
- Claude Pro subscription ($20/month).
Keep everything running
No action needed. Choose this if you are still actively building on the TipCalculator app or plan to start a new Android project soon.
- Android Studio and the emulator stay installed for future projects.
- Claude Code remains available in your terminal for any coding task.
- Your TipCalculator project stays at ~/AndroidStudioProjects/TipCalculator ready to open anytime.
- Your Claude Pro subscription continues at $20/month.
Pause - I'll come back to this later
Shut down running processes to free up system resources. Your files and installations stay intact for when you return.
- Stop the Android Emulator if it is still running by clicking the X button on the emulator window.
- Quit Android Studio by clicking Android Studio in the menu bar, then clicking Quit Android Studio.
- Your project files, Claude Code installation, and Android SDK remain on disk for next time.
- If you want to pause your Claude Pro subscription, visit your account settings at claude.ai to manage your plan.
Delete - I don't want to use this again
Remove all project resources and start fresh. Follow these steps to clean up everything.
- Delete the TipCalculator project folder by running this in Terminal:
rm -rf ~/AndroidStudioProjects/TipCalculator
- Remove Claude Code. If you installed using the native installer, run:
rm -f ~/.local/bin/claude
rm -rf ~/.local/share/claude
rm -rf ~/.claude
rm -f ~/.claude.json
- If you installed Claude Code via Homebrew instead, run:
brew uninstall --cask claude-code
rm -rf ~/.claude
rm -f ~/.claude.json
- Remove Android Studio by dragging it from your Applications folder to the Trash. Then remove the SDK and related data directories:
rm -rf ~/Library/Android/sdk
rm -rf ~/Library/Application\ Support/Google/AndroidStudio*
rm -rf ~/Library/Caches/Google/AndroidStudio*
rm -rf ~/Library/Logs/Google/AndroidStudio*
- If you want to cancel your Claude Pro subscription, sign in at claude.ai. Click your profile icon, then select Settings. Open the Subscription section and follow the cancellation steps.
Nice Work!
Nice Work!
You just built your first Android app with an AI pair programmer. You now have a working Tip Calculator running on your emulator and a repeatable workflow for building Android apps with Claude Code.
You've learned how to:
- Build a complete Tip Calculator Android app with Jetpack Compose and Material 3, including input validation, custom sliders, and reactive calculations.
- Use Claude Code as an AI pair programmer for Android development by describing what you want, reviewing generated code, and iterating on the results.
- Create a CLAUDE.md file to give Claude Code persistent project context about your tech stack and conventions.
- Added bill-splitting functionality that divides the tip and total among multiple people for group dinners.
Ready to quiz yourself?