Overview
This app aims to simplify the process of calculating and managing tips for various services, enhancing the overall user experience. Here's a breakdown of the key features and functionalities:
User Interface Elements
The app includes essential UI elements such as an EditText for entering the base amount, a SeekBar for selecting tip percentages, and TextViews to display calculated tip amounts, total amounts, and a descriptive tip rating.
Real-time Updates
The app provides real-time updates as users input the base amount or adjust the tip percentage using the SeekBar. The calculations for tip amount, total amount, and tip description are dynamically updated.
Dynamic Tip Description
The tip description is dynamically determined based on the selected tip percentage. It categorizes tips into different levels (e.g., Poor, Acceptable, Good, Great, Excellent) with corresponding color-coding for better user understanding.
Tip Calculation
The core functionality lies in the accurate calculation of the tip and total amount based on the entered base amount and the selected tip percentage.
Input Validation
The app performs input validation to ensure that the base amount is a valid numeric value. If not, it defaults to a base amount of 0.0.
Color-Coded Feedback
The app utilizes color-coding to visually represent the quality of the tip, providing users with an intuitive and quick understanding of their tipping choice.
Conclusion
This Tipping App not only streamlines the tipping process but also adds a user-friendly touch with dynamic feedback, making it easy for users to choose an appropriate tip amount. The code is well-structured, utilizing Android's UI components and event listeners effectively to create a responsive and interactive user experience.
MainActivity.kt
package com.example.tippy
import android.content.res.ColorStateList
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import android.widget.SeekBar
import android.widget.TextView
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private lateinit var etBaseAmount: EditText
private lateinit var seekBarTip: SeekBar
private lateinit var tvTipPercent: TextView
private lateinit var tvTipAmount: TextView
private lateinit var tvTotalAmount: TextView
private lateinit var tvTipDescription: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
etBaseAmount = findViewById(R.id.etBaseAmount)
seekBarTip = findViewById(R.id.seekBarTip)
tvTipPercent = findViewById(R.id.tvTipPercent)
tvTipAmount = findViewById(R.id.tvTipAmount)
tvTotalAmount = findViewById(R.id.tvTotalAmount)
tvTipDescription = findViewById(R.id.tvTipDescription)
etBaseAmount.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) {
updateTipAndTotal()
}
override fun afterTextChanged(s: Editable?) {
}
})
seekBarTip.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
tvTipPercent.text = "$progress%"
updateTipAndTotal()
updateTipDescription(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
}
private fun updateTipAndTotal() {
val baseAmount = etBaseAmount.text.toString().toDoubleOrNull() ?: 0.0
val tipPercentage = seekBarTip.progress
val tipAmount = (baseAmount * tipPercentage / 100)
val totalAmount = baseAmount + tipAmount
tvTipAmount.text = String.format("%.2f", tipAmount)
tvTotalAmount.text = String.format("%.2f", totalAmount)
}
private fun updateTipDescription(tipPercent: Int) {
val tipDescription = when (tipPercent) {
in 0..8 -> {
tvTipDescription.setTextColor(ContextCompat.getColor(this, R.color.poorColor))
"Poor"
}
in 9..14 -> {
tvTipDescription.setTextColor(ContextCompat.getColor(this, R.color.acceptableColor))
"Acceptable"
}
in 15..19 -> {
tvTipDescription.setTextColor(ContextCompat.getColor(this, R.color.goodColor))
"Good"
}
in 20..24 -> {
tvTipDescription.setTextColor(ContextCompat.getColor(this, R.color.greatColor))
"Great"
}
else -> {
tvTipDescription.setTextColor(ContextCompat.getColor(this, R.color.excellentColor))
"Excellent"
}
}
tvTipDescription.text = tipDescription
}
}
activity_main.xml
version="1.0" encoding="utf-8"
?xml version="1.0" encoding="utf-8"?>
androidx.constraintlayout.widget.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
TextView
android:id="@+id/tvBaseLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="48dp"
android:text="Base"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
TextView
android:id="@+id/tvTipPercent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvBaseLabel"
tools:text="24%" />
TextView
android:id="@+id/tvTipLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Tip"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintTop_toBottomOf="@+id/tvTipPercent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
TextView
android:id="@+id/tvTotalLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:text="Total"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintTop_toBottomOf="@+id/tvTipLabel"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
EditText
android:id="@+id/etBaseAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="8"
android:hint="Bill Amount"
android:inputType="numberDecimal"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="@+id/tvBaseLabel"
app:layout_constraintTop_toTopOf="@+id/tvBaseLabel"
app:layout_constraintStart_toEndOf="@+id/tvBaseLabel"
app:layout_constraintEnd_toEndOf="parent" />
SeekBar
android:id="@+id/seekBarTip"
android:layout_width="207dp"
android:layout_height="14dp"
android:max="30"
app:layout_constraintBottom_toBottomOf="@+id/tvTipPercent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tvTipPercent"
app:layout_constraintTop_toTopOf="@+id/tvTipPercent" />
TextView
android:id="@+id/tvTipAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="@+id/tvTipLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tvTipLabel"
app:layout_constraintTop_toTopOf="@+id/tvTipLabel"
tools:text="19.96" />
TextView
android:id="@+id/tvTotalAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="@+id/tvTotalLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tvTotalLabel"
app:layout_constraintTop_toTopOf="@+id/tvTotalLabel"
tools:text="103.11" />
TextView
android:id="@+id/tvTipDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Description"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintTop_toBottomOf="@+id/tvTotalAmount"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
androidx.constraintlayout.widget.ConstraintLayout>
Flowchart
This section will contain a flowchart depicting the workflow of the Tipping App.
Flowchart Code
flowchart TD
subgraph Initialization
A[Initialize Views]
B[Set Event Listeners]
C[Set Initial Values]
A --> B --> C
end
subgraph UserInteraction
D[Enter Base Amount]
E[Adjust Tip Percentage]
D --> E
end
subgraph UpdateLogic
F[Update Tip and Total]
G[Update Tip Description]
F --> G
end
subgraph Display
H[Display Tip Amount]
I[Display Total Amount]
J[Display Tip Description]
H --> I --> J
end
A --> D
E --> F
G --> H
Sequence Diagram
This section will contain a sequence diagram illustrating the interactions between components in the Tipping App.
Sequence Diagram Code
sequenceDiagram
participant User
participant MainActivity
participant EditText as etBaseAmount
participant SeekBar as seekBarTip
participant TextView as tvTipPercent
participant TextView as tvTipAmount
participant TextView as tvTotalAmount
participant TextView as tvTipDescription
User->>MainActivity: Launch App
MainActivity->>MainActivity: Initialize Views, Set Listeners, Set Initial Values
loop User Interaction
User->>etBaseAmount: Enter Base Amount
User->>seekBarTip: Adjust Tip Percentage
end
alt Text Changed
etBaseAmount->>MainActivity: Text Changed
MainActivity->>MainActivity: Update Tip and Total
MainActivity->>MainActivity: Update Tip Description
MainActivity->>tvTipAmount: Display Tip Amount
MainActivity->>tvTotalAmount: Display Total Amount
MainActivity->>tvTipDescription: Display Tip Description
else SeekBar Changed
seekBarTip->>MainActivity: SeekBar Changed
MainActivity->>MainActivity: Update Tip and Total
MainActivity->>tvTipPercent: Display Updated Tip Percentage
MainActivity->>tvTipAmount: Display Tip Amount
MainActivity->>tvTotalAmount: Display Total Amount
MainActivity->>tvTipDescription: Display Tip Description
end