Tipping App for Android

January 2024

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>

							
                        
                    

App Screenshots

Tipping App Screen 1
Tipping App Screen 2

Flowchart

This section will contain a flowchart depicting the workflow of the Tipping App.

Flowchart
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
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