¿Cómo construir la aplicación de Android SIP Calculator usando la arquitectura MVP?

SIP, el Plan Sistemático de Inversiones. Uno de los métodos para invertir en Fondos Mutuos es semanal, mensual trimestral o semestral. La calculadora SIP es la herramienta para que los inversores se hagan una idea sobre el rendimiento de sus inversiones. Sin embargo, los rendimientos de los fondos mutuos varían según varios factores. Por ejemplo, la calculadora SIP no calcula los rendimientos absolutos porque algunos fondos mutuos tienen carga de salida y tasa de gastos cargada. Por lo tanto, solo calcula rendimientos estimados y proporciona el resultado del valor de vencimiento. Este artículo ha sido discutido, implementando la calculadora SIP en Android con una arquitectura MVP robusta. Eche un vistazo a lo siguiente para tener una idea del producto final.

Build SIP Calculator Android App using MVP Architecture

¿Cómo ayuda la calculadora de devolución SIP?

Los SIP brindan rendimientos muy lucrativos en comparación con las inversiones de suma global en fondos mutuos. La calculadora SIP ayuda a los inversores a hacer planes de inversión a largo plazo, ya que proporciona lo siguiente:

  1. Determina la cantidad total invertida a lo largo del tiempo.
  2. Informa sobre los rendimientos estimados sobre la tasa de rendimiento esperada.
  3. También calcula el valor de vencimiento, que es la rentabilidad estimada + el monto total invertido .

Nota: Los rendimientos estimados son simplemente el valor de vencimiento: el monto total invertido .

La fórmula para calcular los rendimientos SIP es simple.

metro = pags * ( { ( 1 + yo ) ^ norte – 1 } / yo ) * ( yo + 1 )

m -> Valor al Vencimiento (Retorno Estimado + Monto Total Invertido).

p -> monto principal (a invertir mensualmente).

i -> tasa de interés del período.

n -> numero de pagos realizados.

Beneficios que uno obtiene de esta calculadora

  • Con base en el rendimiento estimado, se pueden planificar inversiones a largo plazo en fondos mutuos.
  • Proporciona estimaciones precisas.
  • De acuerdo con sus necesidades financieras, ayuda a dar forma a su cartera al proporcionar precisión en relación con el rendimiento anterior de su fondo mutuo investigado.

Antes de ir a la implementación, algunos requisitos previos

Pasos para implementar la Calculadora SIP en Android

Paso 1: Crear un nuevo proyecto

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación.

Paso 2: trabajar con el archivo activity_main.xml

El diseño principal de la aplicación contiene 3 textos de edición y controles deslizantes asociados con ellos para que los usuarios puedan deslizar y realizar cambios en el texto de edición en lugar de escribir. Un botón Calcular que al pulsarlo calcula según la fórmula mencionada. Uno es un gráfico circular y este gráfico circular tiene dos sectores, uno es para el monto invertido durante el período y otro sector es el rendimiento estimado de la inversión generada sobre la tasa de rendimiento esperada y la tenencia seleccionada. Para implementar lo mismo, invoque el siguiente código dentro del archivo activity_main.xml.

XML

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
    android:clipToPadding="false"
    tools:context=".View.SipCalculatorView"
    tools:ignore="HardcodedText">
  
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
  
        <androidx.cardview.widget.CardView
            android:id="@+id/monthlyInvestmentAmountCardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp"
            app:cardMaxElevation="6dp"
            app:cardPreventCornerOverlap="true"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
  
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="12dp">
  
                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/monthlyInvestmentAmountTextInputLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Monthly Investment Amount (in Rs.)"
                    app:layout_constraintTop_toTopOf="parent"
                    tools:layout_editor_absoluteX="8dp">
  
                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/monthlyInvestmentAmountTextInputEditText"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:inputType="number" />
  
                </com.google.android.material.textfield.TextInputLayout>
  
                <com.google.android.material.slider.Slider
                    android:id="@+id/monthlyInvestmentAmountSlider"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dp"
                    android:stepSize="5000"
                    android:valueFrom="5000"
                    android:valueTo="50000"
                    app:layout_constraintTop_toBottomOf="@id/monthlyInvestmentAmountTextInputLayout"
                    tools:layout_editor_absoluteX="8dp" />
  
            </androidx.constraintlayout.widget.ConstraintLayout>
  
        </androidx.cardview.widget.CardView>
  
        <androidx.cardview.widget.CardView
            android:id="@+id/expectedReturnRateCardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp"
            app:cardMaxElevation="6dp"
            app:cardPreventCornerOverlap="true"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/monthlyInvestmentAmountCardView">
  
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="12dp">
  
                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/expectedReturnRateTextInputLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Expected Rate of Return (in %)"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent">
  
                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/expectedReturnRateTextInputEditText"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:inputType="number" />
  
                </com.google.android.material.textfield.TextInputLayout>
  
                <com.google.android.material.slider.Slider
                    android:id="@+id/expectedReturnRateSlider"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dp"
                    android:stepSize="1"
                    android:valueFrom="5"
                    android:valueTo="30"
                    app:layout_constraintTop_toBottomOf="@id/expectedReturnRateTextInputLayout"
                    tools:layout_editor_absoluteX="12dp" />
  
            </androidx.constraintlayout.widget.ConstraintLayout>
  
        </androidx.cardview.widget.CardView>
  
        <androidx.cardview.widget.CardView
            android:id="@+id/investmentTimePeriodCardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp"
            app:cardMaxElevation="6dp"
            app:cardPreventCornerOverlap="true"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/expectedReturnRateCardView">
  
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="12dp">
  
                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/investmentTimePeriodTextInputLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Investment Time Period (in Years)"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent">
  
                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/investmentTimePeriodTextInputEditText"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:inputType="number" />
  
                </com.google.android.material.textfield.TextInputLayout>
  
                <com.google.android.material.slider.Slider
                    android:id="@+id/investmentTimePeriodSlider"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dp"
                    android:stepSize="1"
                    android:valueFrom="5"
                    android:valueTo="30"
                    app:layout_constraintTop_toBottomOf="@id/investmentTimePeriodTextInputLayout"
                    tools:layout_editor_absoluteX="12dp" />
  
            </androidx.constraintlayout.widget.ConstraintLayout>
  
        </androidx.cardview.widget.CardView>
  
        <com.google.android.material.button.MaterialButton
            android:id="@+id/sipCalculateResultButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:text="CALCULATE"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/investmentTimePeriodCardView" />
  
        <androidx.cardview.widget.CardView
            android:id="@+id/sipCalculationResultCardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp"
            app:cardMaxElevation="6dp"
            app:cardPreventCornerOverlap="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/sipCalculateResultButton">
  
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="16dp">
  
                <View
                    android:id="@+id/view"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:background="@color/green_200"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="@+id/totalInvestedAmountMaterialHeading" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/totalInvestedAmountMaterialHeading"
                    style="@style/TextAppearance.MdcTypographyStyles.Subtitle1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="8dp"
                    android:text="Invested Amount"
                    app:layout_constraintStart_toEndOf="@+id/view"
                    app:layout_constraintTop_toTopOf="parent" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/totalInvestedAmountMaterialTextView"
                    style="@style/TextAppearance.MdcTypographyStyles.Headline6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="2dp"
                    app:layout_constraintStart_toStartOf="@+id/totalInvestedAmountMaterialHeading"
                    app:layout_constraintTop_toBottomOf="@+id/totalInvestedAmountMaterialHeading"
                    tools:text="10000" />
  
                <View
                    android:id="@+id/view2"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:background="@color/blue_200"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="@+id/estimatedReturnsMaterialHeading" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/estimatedReturnsMaterialHeading"
                    style="@style/TextAppearance.MdcTypographyStyles.Subtitle1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="8dp"
                    android:layout_marginTop="12dp"
                    android:text="Estimated Returns"
                    app:layout_constraintStart_toEndOf="@+id/view2"
                    app:layout_constraintTop_toBottomOf="@+id/totalInvestedAmountMaterialTextView" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/estimatedReturnsMaterialTextView"
                    style="@style/TextAppearance.MdcTypographyStyles.Headline6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="2dp"
                    app:layout_constraintStart_toStartOf="@+id/estimatedReturnsMaterialHeading"
                    app:layout_constraintTop_toBottomOf="@+id/estimatedReturnsMaterialHeading"
                    tools:text="25000" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/totalAmountMaterialHeading"
                    style="@style/TextAppearance.MdcTypographyStyles.Subtitle1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="12dp"
                    android:text="Total Amount"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/estimatedReturnsMaterialTextView" />
  
                <com.google.android.material.textview.MaterialTextView
                    android:id="@+id/totalAmountMaterialTextView"
                    style="@style/TextAppearance.MdcTypographyStyles.Headline6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="2dp"
                    app:layout_constraintStart_toStartOf="@+id/totalAmountMaterialHeading"
                    app:layout_constraintTop_toBottomOf="@+id/totalAmountMaterialHeading"
                    tools:text="35000" />
  
                <org.eazegraph.lib.charts.PieChart
                    android:id="@+id/sipResultPieChart"
                    android:layout_width="128dp"
                    android:layout_height="128dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
  
            </androidx.constraintlayout.widget.ConstraintLayout>
  
        </androidx.cardview.widget.CardView>
  
    </androidx.constraintlayout.widget.ConstraintLayout>
  
</ScrollView>

Sin embargo, lo siguiente es opcional, la aplicación está marcada con el sistema de tipo Roboto sugerido por Google Material Design. Incluya el siguiente código dentro del archivo themes.xml .

XML

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.GFGSIPCalculator" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/green_500</item>
        <item name="colorPrimaryVariant">@color/green_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline1" parent="TextAppearance.MaterialComponents.Headline1">
        <item name="fontFamily">@font/roboto_light</item>
        <item name="android:fontFamily">@font/roboto_light</item>
        <item name="android:textSize">96sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline2" parent="TextAppearance.MaterialComponents.Headline2">
        <item name="fontFamily">@font/roboto_light</item>
        <item name="android:fontFamily">@font/roboto_light</item>
        <item name="android:textSize">60sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline3" parent="TextAppearance.MaterialComponents.Headline3">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">48sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline4" parent="TextAppearance.MaterialComponents.Headline4">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">34sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline5" parent="TextAppearance.MaterialComponents.Headline5">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">24sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Headline6" parent="TextAppearance.MaterialComponents.Headline6">
        <item name="fontFamily">@font/roboto_medium</item>
        <item name="android:fontFamily">@font/roboto_medium</item>
        <item name="android:textSize">20sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Subtitle1" parent="TextAppearance.MaterialComponents.Subtitle1">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">16sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Subtitle2" parent="TextAppearance.MaterialComponents.Subtitle2">
        <item name="fontFamily">@font/roboto_medium</item>
        <item name="android:fontFamily">@font/roboto_medium</item>
        <item name="android:textSize">14sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Body1" parent="TextAppearance.MaterialComponents.Body1">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">16sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Body2" parent="TextAppearance.MaterialComponents.Body2">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">14sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Button" parent="TextAppearance.MaterialComponents.Button">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">14sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Caption" parent="TextAppearance.MaterialComponents.Caption">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">12sp</item>
    </style>
  
    <style name="TextAppearance.MdcTypographyStyles.Overline" parent="TextAppearance.MaterialComponents.Overline">
        <item name="fontFamily">@font/roboto_regular</item>
        <item name="android:fontFamily">@font/roboto_regular</item>
        <item name="android:textSize">10sp</item>
    </style>
  
</resources>

Paso 3: trabajar con la arquitectura

Como los componentes de la arquitectura necesarios para esta aplicación son pequeños pero fáciles de mantener y documentar y escalar la aplicación. Entonces, la siguiente imagen representa que uno debe crear clases de componentes de arquitectura e interfaz asociada, ya que la interfaz aquí se denomina contrato, en la arquitectura MVP. Cree un paquete para cada componente de la arquitectura.

Paso 4: Trabajar con todas las interfaces (contratos) de la arquitectura

SipCalculatorModelInterfaz:

Kotlin

interface SipCalculatorModelInterface {
    fun getTotalInvestedAmount(): Long
    fun getEstimatedReturns(): Long
    fun getTotalValue(): Long
}

SipCalculatorPresenterInterfaz:

Kotlin

interface SipCalculatorPresenterInterface {
    fun forCalculation(
        monthlyInvestmentAmount: String,
        expectedReturnRate: String,
        investmentTimePeriod: String
    )
}

SipCalculatorViewInterfaz:

Kotlin

interface SipCalculatorViewInterface {
    fun onCalculationResult(
        totalInvestedAmount: String,
        estimatedReturns: String,
        totalValue: String
    )
}

Paso 5: trabajar con la clase SipCalculatorModel.kt

Esta clase implementa SipCalculatorModelInterface. y esto contiene la lógica principal que está calculando todos los resultados. Se agregan comentarios para una mejor comprensión.

Kotlin

class SipCalculatorModel(
    monthlyInvestmentAmount: String,
    expectedReturnRate: String,
    investmentTimePeriod: String
    ) : SipCalculatorModelInterface {
  
    val TAG = SipCalculatorModel::class.java.simpleName
  
    // convert all the inputs to integer.
    private var monthlyInvestmentAmountInt: Int = monthlyInvestmentAmount.toInt()
    private var expectedReturnRateInt: Int = expectedReturnRate.toInt()
    private var investmentTimePeriodInt: Int = investmentTimePeriod.toInt() * 12
  
    // total investment is considered here is according to monthly investment plans
    override fun getTotalInvestedAmount(): Long {
        return (monthlyInvestmentAmountInt * investmentTimePeriodInt).toLong()
    }
  
    // estimated returns = maturity value - total investment amount
    override fun getEstimatedReturns(): Long {
        return getTotalValue() - getTotalInvestedAmount()
    }
  
    // calculate the maturity value according to the formula
    override fun getTotalValue(): Long {
        val periodicInterest: Float = ((expectedReturnRateInt.toFloat() / 12) / 100)
  
        return (monthlyInvestmentAmountInt * (((Math.pow(
            (1 + periodicInterest).toDouble(),
            investmentTimePeriodInt.toDouble()
        )
                - 1) / periodicInterest) * (1 + periodicInterest)))
            .toLong()
    }
}

Paso 6: trabajar con la clase SipCalculatorPresenter.kt

Esta clase implementa SipCalculatorPresenterInterface, esto simplemente actúa entre SipCalculatorModel y SipCalculatorView. Invoque el siguiente código dentro de la clase SipCalculatorPresenter.kt. Se agregan comentarios para una mejor comprensión.

Kotlin

import com.adityamshidlyali.gfgsipcalculator.Model.SipCalculatorModel
import com.adityamshidlyali.gfgsipcalculator.View.SipCalculatorViewInterface
  
class SipCalculatorPresenter(
    private val sipCalculatorViewInterface: SipCalculatorViewInterface
    ) : SipCalculatorPresenterInterface {
  
    override fun forCalculation(
        monthlyInvestmentAmount: String,
        expectedReturnRate: String,
        investmentTimePeriod: String
    ) {
  
        // create instance of the sip model and calculate all the results.
        val sipModel = SipCalculatorModel(
            monthlyInvestmentAmount,
            expectedReturnRate,
            investmentTimePeriod
        )
  
        // pass the data to view by accepting the context of the view class
        sipCalculatorViewInterface.onCalculationResult(
            sipModel.getTotalInvestedAmount().toString(),
            sipModel.getEstimatedReturns().toString(),
            sipModel.getTotalValue().toString()
        )
    }
}

Paso 7: trabajar con la clase SipCalculatorView.kt

Esta clase implementa SipCalculatorViewInterface y el contexto de esta clase se proporciona a la clase Presenter para obtener el resultado calculado. Y crea instancias de cada elemento de la interfaz de usuario y, después de obtener los resultados calculados del presentador, actualiza los elementos de la interfaz de usuario. Para implementar lo mismo, invoque el siguiente código dentro de la clase SipCalculatorView.kt. Se agregan comentarios para una mejor comprensión.

Kotlin

import android.annotation.SuppressLint
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.adityamshidlyali.gfgsipcalculator.Presenter.SipCalculatorPresenter
import com.adityamshidlyali.gfgsipcalculator.R
import com.google.android.material.button.MaterialButton
import com.google.android.material.slider.Slider
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.android.material.textview.MaterialTextView
import org.eazegraph.lib.charts.PieChart
import org.eazegraph.lib.models.PieModel
import java.text.NumberFormat
import java.util.*
  
class SipCalculatorView : AppCompatActivity(), SipCalculatorViewInterface {
  
    // material text views
    private lateinit var totalInvestedAmountMaterialTextView: MaterialTextView
    private lateinit var estimatedReturnsMaterialTextView: MaterialTextView
    private lateinit var totalAmountMaterialTextView: MaterialTextView
  
    // material text input edit texts and text input layout
    private lateinit var monthlyInvestmentAmountTextInputEditText: TextInputEditText
    private lateinit var expectedReturnRateTextInputEditText: TextInputEditText
    private lateinit var investmentTimePeriodTextInputEditText: TextInputEditText
    private lateinit var monthlyInvestmentAmountTextInputLayout: TextInputLayout
    private lateinit var expectedReturnRateTextInputLayout: TextInputLayout
    private lateinit var investmentTimePeriodTextInputLayout: TextInputLayout
  
    // buttons
    private lateinit var sipCalculateResultButton: MaterialButton
  
    // pie chart
    private lateinit var sipResultPieChart: PieChart
  
    // calculation result strings
    private lateinit var monthlyInvestmentAmount: String
    private lateinit var expectedReturnRate: String
    private lateinit var investmentTimePeriod: String
  
    // sliders
    private lateinit var monthlyInvestmentAmountSlider: Slider
    private lateinit var expectedReturnRateSlider: Slider
    private lateinit var investmentTimePeriodSlider: Slider
  
    @SuppressLint("UseCompatLoadingForDrawables", "SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
         
        // initialise all the UI elements
          
          
        // material textViews
        totalInvestedAmountMaterialTextView = findViewById(R.id.totalInvestedAmountMaterialTextView)
        estimatedReturnsMaterialTextView = findViewById(R.id.estimatedReturnsMaterialTextView)
        totalAmountMaterialTextView = findViewById(R.id.totalAmountMaterialTextView)
  
        // material text input editTexts and text input layout
        monthlyInvestmentAmountTextInputEditText =
            findViewById(R.id.monthlyInvestmentAmountTextInputEditText)
        expectedReturnRateTextInputEditText =
            findViewById(R.id.expectedReturnRateTextInputEditText)
        investmentTimePeriodTextInputEditText =
            findViewById(R.id.investmentTimePeriodTextInputEditText)
        monthlyInvestmentAmountTextInputLayout =
            findViewById(R.id.monthlyInvestmentAmountTextInputLayout)
        expectedReturnRateTextInputLayout =
            findViewById(R.id.expectedReturnRateTextInputLayout)
        investmentTimePeriodTextInputLayout =
            findViewById(R.id.investmentTimePeriodTextInputLayout)
  
        // buttons
        sipCalculateResultButton = findViewById(R.id.sipCalculateResultButton)
  
        // pie chart
        sipResultPieChart = findViewById(R.id.sipResultPieChart)
  
        // sliders
        monthlyInvestmentAmountSlider = findViewById(R.id.monthlyInvestmentAmountSlider)
        expectedReturnRateSlider = findViewById(R.id.expectedReturnRateSlider)
        investmentTimePeriodSlider = findViewById(R.id.investmentTimePeriodSlider)
  
          
        // setting initial values to all the UI elements
           
        // TextInputEditTexts
        monthlyInvestmentAmountTextInputEditText.setText("5000")
        expectedReturnRateTextInputEditText.setText("14")
        investmentTimePeriodTextInputEditText.setText("10")
  
        // sliders
        monthlyInvestmentAmountSlider.value = 5000f
        expectedReturnRateSlider.value = 14f
        investmentTimePeriodSlider.value = 10f
  
        val sipPresenter = SipCalculatorPresenter(this)
        sipPresenter.forCalculation(
            "5000",
            "14",
            "10"
        )
  
          
        // handling all listeners for all the UI elements
           
        // handling sliders
        monthlyInvestmentAmountSlider.addOnChangeListener { slider, value, fromUser ->
            monthlyInvestmentAmountTextInputEditText.setText(value.toInt().toString())
        }
        expectedReturnRateSlider.addOnChangeListener { slider, value, fromUser ->
            expectedReturnRateTextInputEditText.setText(value.toInt().toString())
        }
        investmentTimePeriodSlider.addOnChangeListener { slider, value, fromUser ->
            investmentTimePeriodTextInputEditText.setText(value.toInt().toString())
        }
  
        // handling buttons
        sipCalculateResultButton.setOnClickListener {
  
            monthlyInvestmentAmount = monthlyInvestmentAmountTextInputEditText.text.toString()
            expectedReturnRate = expectedReturnRateTextInputEditText.text.toString()
            investmentTimePeriod = investmentTimePeriodTextInputEditText.text.toString()
  
            if (checkAllFields()) {
                sipPresenter.forCalculation(
                    monthlyInvestmentAmount,
                    expectedReturnRate,
                    investmentTimePeriod
                )
            }
        }
    }
  
    // update the text views in the
    // result section of the view
    // and also update the pie chart
    override fun onCalculationResult(
        totalInvestedAmount: String,
        estimatedReturns: String,
        totalValue: String
    ) {
  
        val currencyFormatter: NumberFormat =
            NumberFormat.getCurrencyInstance(Locale("en", "IN", "#"))
  
        val totalInvestedAmountFormatted: String =
            currencyFormatter.format(totalInvestedAmount.toLong())
        val estimatedReturnsFormatted: String = currencyFormatter.format(estimatedReturns.toLong())
        val totalValueFormatted: String = currencyFormatter.format(totalValue.toLong())
  
        totalInvestedAmountMaterialTextView.text = totalInvestedAmountFormatted
        estimatedReturnsMaterialTextView.text = estimatedReturnsFormatted
        totalAmountMaterialTextView.text = totalValueFormatted
  
        sipResultPieChart.clearAnimation()
        sipResultPieChart.clearChart()
  
        sipResultPieChart.addPieSlice(
            PieModel(
                "Invested Amount",
                totalInvestedAmount.toFloat(),
                ContextCompat.getColor(this, R.color.blue_200)
            )
        )
  
        sipResultPieChart.addPieSlice(
            PieModel(
                "Estimated Returns",
                totalValue.toFloat() - totalInvestedAmount.toFloat(),
                ContextCompat.getColor(this, R.color.green_200)
            )
        )
  
        sipResultPieChart.startAnimation()
    }
  
    // check whether all the text fields are filled or not
    private fun checkAllFields(): Boolean {
        if (monthlyInvestmentAmount.isEmpty()) {
            monthlyInvestmentAmountTextInputEditText.error = "Can't be empty"
            return false
        }
  
        if (expectedReturnRate.isEmpty()) {
            expectedReturnRateTextInputEditText.error = "Can't be empty"
            return false
        }
  
        if (investmentTimePeriod.isEmpty()) {
            investmentTimePeriodTextInputEditText.error = "Can't be empty"
            return false
        }
  
        return true
    }
}

Producción:

Publicación traducida automáticamente

Artículo escrito por adityamshidlyali y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *