Skip to content

WA3. Kotlin OOP

1. BMI Calculator

  • The code below will calculate your BMI and display the result in the screen.
  • see the screen shots below

// FirstFragment.kt
package com.example.cs4405_02

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.example.cs4405_02.databinding.FragmentFirstBinding
import android.graphics.Color

enum class BMI_DATA(
    val range: ClosedFloatingPointRange<Double>,
    val message: String,
    val color: Int
) {
    UNDERWEIGHT(0.0..18.5, "You are underweight", Color.YELLOW),
    NORMAL(18.5..24.9, "Your weight is normal", Color.GREEN),
    OVERWEIGHT(25.0..Double.MAX_VALUE, "You are overweight", Color.RED);

    companion object {
        fun get(bmi: Double): BMI_DATA {
            return values().first { it.range.contains(bmi) }
        }
    }
}


fun calculateBMI(
    weight: Double,
    height: Double,
    gender: String
): Double {
    return weight / ((height.toDouble() / 100) * (height / 100)) // height is in cm, so divided by 100 to convert it to meters
}

/**
 * A simple [Fragment] subclass as the default destination in the navigation.
 */
class FirstFragment : Fragment() {

    private var _binding: FragmentFirstBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentFirstBinding.inflate(inflater, container, false)
        return binding.root

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.calculate.setOnClickListener {
            val weight = binding.weight.text.toString().toDouble()
            val height = binding.height.text.toString().toDouble()
            val gender = if (binding.male.isChecked) "Male" else "Female"

            val bmiScore = calculateBMI(weight, height, gender)
            val bmi = BMI_DATA.get(bmiScore)

            binding.result.text = "Your BMI: $bmiScore. ${bmi.message}"
            binding.result.setTextColor(bmi.color)
            binding.result.visibility = View.VISIBLE

        }

        binding.buttonFirst.setOnClickListener {
            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)

        }


    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
<!-- fragment_first.xml -->
<?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=".FirstFragment"
    >


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="112dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.554"
        app:layout_constraintStart_toStartOf="parent">


        <TextView
            android:id="@+id/result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            android:textSize="30sp"
            android:visibility="gone"
            />

        <EditText
            android:id="@+id/weight"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter weight in kg" />

        <EditText
            android:id="@+id/height"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter height in cm" />

        <RadioGroup
            android:id="@+id/gender"
            android:layout_width="358dp"
            android:layout_height="wrap_content">

            <RadioButton
                android:id="@+id/male"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Male" />

            <RadioButton
                android:id="@+id/female"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Female" />
        </RadioGroup>

        <Button
            android:id="@+id/calculate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Calculate BMI" />

        <Button
            android:id="@+id/button_first"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="112dp"
            android:text="Open Calculator"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.1"
            app:layout_constraintStart_toStartOf="parent" />
    </LinearLayout>



</androidx.constraintlayout.widget.ConstraintLayout>

2. Calculator

  • The calculator will perform basic arithmetic operations.
  • It is another fragment within the same activity.
  • You can go between the two fragments using the buttons.
  • screenshots below

package com.example.cs4405_02

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.example.cs4405_02.databinding.FragmentSecondBinding


enum class Operations {
    ADD,
    SUBTRACT,
    MULTIPLY,
    DIVIDE
}


class Calculator(private val operand1: Double, private val operand2: Double) {
    fun calculate(operation: Operations): Double {
        return when (operation) {
            Operations.ADD -> operand1 + operand2
            Operations.SUBTRACT -> operand1 - operand2
            Operations.MULTIPLY -> operand1 * operand2
            Operations.DIVIDE -> if (operand2 != 0.0) operand1 / operand2 else Double.NaN
        }
    }
}

/**
 * A simple [Fragment] subclass as the second destination in the navigation.
 */
class SecondFragment : Fragment() {

    private var _binding: FragmentSecondBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        _binding = FragmentSecondBinding.inflate(inflater, container, false)
        return binding.root

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.buttonSecond.setOnClickListener {
            findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
        }

        binding.calculate.setOnClickListener {
            val op1 = binding.operand1.text.toString().toDouble()
            val op2 = binding.operand2.text.toString().toDouble()
            val _op = binding.operation.selectedItem.toString()
            val operation = when (_op) {
                "ADD" -> Operations.ADD
                "SUBTRACT" -> Operations.SUBTRACT
                "MULTIPLY" -> Operations.MULTIPLY
                "DIVIDE" -> Operations.DIVIDE
                else -> throw IllegalArgumentException("Unknown operation.")
            }

            val calculator = Calculator(op1, op2)
            val result = calculator.calculate(operation)
            binding.result.text = result.toString()


        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
<!-- fragment_second.xml -->
<?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=".SecondFragment">

    <TextView
        android:id="@+id/textview_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@id/button_second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">

        <EditText
            android:id="@+id/operand1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="numberDecimal"
            android:hint="Enter first number"/>

        <EditText
            android:id="@+id/operand2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="numberDecimal"
            android:hint="Enter second number"
            android:layout_marginTop="10dp"/>

        <Spinner
            android:id="@+id/operation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:entries="@array/operations"
            android:layout_marginTop="10dp"/>

        <Button
            android:id="@+id/calculate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Calculate"
            android:layout_marginTop="10dp"/>

        <TextView
            android:id="@+id/result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30sp"
            android:layout_marginTop="10dp"/>

    </LinearLayout>


    <Button
        android:id="@+id/button_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="To BMI"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview_second" />
</androidx.constraintlayout.widget.ConstraintLayout>