Belajar Android Kotlin Extension

Yudi Setiawan 21 Juni 2017

Belajar Android Kotlin Extension

Pengenalan

Akhir-akhir ini dunia android developer lagi heboh-hebohnya menyambut bahasa pemrograman baru yang secara resmi baru saja diumumkan di acara Google I/O 2017 bahwa Kotlin secara resmi didukung oleh Google untuk bisa digunakan membangun aplikasi Android. Ketika diumumkannya info tersebut secara serentak para penonton Google I/O 2017 langsung menyambutnya dengan baik terbukti dengan meriahnya tepuk tangan yang diberikan oleh para penonton ketika itu. Jadi, sebenarnya apa itu Kotlin? Kotlin merupakan bahasa pemrograman yang dikeluarkan oleh JetBrains dan didukung oleh Google untuk bisa membangun aplikasi Android. "Apakah hanya Android saja? jawabannya tidak. Berdasarkan dari situs resminya https://kotlinlang.org/ bahwa Kotlin bisa dipakai untuk platform yang berjalan diatas JVM, Android, Browser dan Native. Jadi, ini sound good for me karena, saya belajar bahasa pemrograman yang bisa multiplatform. Di Kotlin, ada salah satu fitur yang menurut penulis cukup bagus digunakan untuk membangun aplikasi Android yakni, namanya adalah Android Kotlin Extension. Tool ini berguna untuk melakukan binding view dari layout di xml ke file kotlin (logic). Umumnya, kalau di Android Java fitur ini sering kita pakai library Butterknife namun, di Kotlin kita bisa pakai Android Kotlin Extension.

Persiapan

Karena saat ini Android Studio versi 3.0 masih tahap preview jadi, penulis memberi saran lebih baik pakai versi yang stabil saja. Penulis saat ini pakai Android Studio versi 2.3.1. Untuk menggunakan kotlin di Android Studio maka, pembaca perlu melakukan install plugin Kotlin. Caranya, buka menu Settings pada projek Android Studio dan pilih submenu Plugins dan ketikkan kotlin di kolom pencarian seperti pada gambar berikut.

Install Plugin Kotlin

Pembuatan Contoh Projek

Adapun pada tutorial kali ini kita akan membuat aplikasi konversi suhu sederhana menggunakan Kotlin di Android Studio. Silakan buat projek baru dengan nama Belajar Kotlin Extension dan package name-nya terserah Anda isi apa. Karena, penulis saat ini pakai Android Studio versi Kotlin yang plugin jadi, setelah projek selesai dibuat maka, projek tersebut harus kita convert ket projek Kotlin. Caranya, pilih menu Tools kemudian, pilih Kotlin dan pilih Configure Kotlin In Project. Kemudian, jika muncul popup maka, pilih Android With Gradle. Dan pilih versi kotlin yang mau Anda pakai.

Konversi Projek ke Kotlin
Konversi Projek ke Kotlin

Konfigurasi file build.gradle

Pada file build.gradle(app), ketikkan apply plugin: 'kotlin-android-extensions' pada bagian paling atas dan pastikan kotlin-stdlib-jre punya si Kotlin sudah di masukkan ke dependencies dan hasil akhir dari file build.gradle(app) akan menjadi seperti berikut.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.ysn.belajarkotlinextension"
        minSdkVersion 21
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
    testCompile 'junit:junit:4.12'
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support:gridlayout-v7:25.3.1'
}

Selain itu, pastikan juga pada file build.gradle(root) seperti berikut ini juga.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.1.2-3'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Catatan: pada saat ini penulis menggunakan kotlin versi 1.1.2-3

Pembuatan Layout

Silakan buka file activity_main.xml dan ubah kode didalamnya menjadi seperti berikut.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="com.ysn.belajarkotlinextension.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/grid_layout_container_keypad_activity_main"
        android:layout_alignParentTop="true"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:paddingTop="@dimen/activity_vertical_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <Spinner
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/app_compat_spinner_unit_temperature_from_activity_main"
                    android:layout_centerVertical="true"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/text_view_value_temperature_from_activity_main"
                    android:layout_centerVertical="true"
                    android:layout_alignParentEnd="true"
                    android:text="0"
                    android:textSize="20sp"
                    android:textStyle="bold"
                    android:textColor="#EF5350"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/text_view_unit_temperature_from_activity_main"
                    android:text="Celcius"
                    android:layout_centerVertical="true"
                    android:layout_alignParentEnd="true"
                    android:layout_below="@+id/text_view_value_temperature_from_activity_main"
                    />

            </RelativeLayout>

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="@android:color/darker_gray"
            />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:paddingTop="@dimen/activity_vertical_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                >

                <Spinner
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/app_compat_spinner_unit_temperature_to_activity_main"
                    android:layout_centerVertical="true"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/text_view_value_temperature_to_activity_main"
                    android:layout_centerVertical="true"
                    android:text="0"
                    android:textSize="20sp"
                    android:textStyle="bold"
                    android:layout_alignParentEnd="true"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/text_view_unit_temperature_to_activity_main"
                    android:text="Celcius"
                    android:layout_alignParentEnd="true"
                    android:layout_below="@+id/text_view_value_temperature_to_activity_main"
                    />

            </RelativeLayout>

        </LinearLayout>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_above="@+id/grid_layout_container_keypad_activity_main"
        android:background="#e0e0e0" />

    <android.support.v7.widget.GridLayout
        android:id="@+id/grid_layout_container_keypad_activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:alignmentMode="alignBounds"
        app:columnCount="4">

        <!--row 0-->
        <Button
            android:id="@+id/button_keypad_1_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="1"
            app:layout_column="0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="0" />

        <Button
            android:id="@+id/button_keypad_2_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="2"
            app:layout_column="1"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="0" />

        <Button
            android:id="@+id/button_keypad_3_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="3"
            app:layout_column="2"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="0" />

        <Button
            android:id="@+id/button_keypad_ac_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="AC"
            app:layout_column="3"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="0"
            app:layout_rowSpan="2" />

        <!--row 1-->
        <Button
            android:id="@+id/button_keypad_4_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="4"
            app:layout_column="0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="1" />

        <Button
            android:id="@+id/button_keypad_5_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="5"
            app:layout_column="1"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="1" />

        <Button
            android:id="@+id/button_keypad_6_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="6"
            app:layout_column="2"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="1" />

        <!--row 2-->
        <Button
            android:id="@+id/button_keypad_7_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="7"
            app:layout_column="0"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="2" />

        <Button
            android:id="@+id/button_keypad_8_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="8"
            app:layout_column="1"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="2" />

        <Button
            android:id="@+id/button_keypad_9_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="9"
            app:layout_column="2"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="2" />

        <Button
            android:id="@+id/button_keypad_backspace_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="X"
            app:layout_column="3"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="2" />

        <!--row 3-->
        <Button
            android:id="@+id/button_keypad_0_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="0"
            app:layout_column="0"
            app:layout_columnSpan="2"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="3" />

        <Button
            android:id="@+id/button_keypad_dot_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="."
            app:layout_column="2"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="3" />

        <Button
            android:id="@+id/button_keypad_plus_minus_activity_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/background_button_keypad"
            android:text="+/-"
            app:layout_column="3"
            app:layout_columnWeight="1"
            app:layout_gravity="fill"
            app:layout_row="3" />

    </android.support.v7.widget.GridLayout>

</RelativeLayout>

Adapun output dari kode layout diatas adalah seperti berikut.

Layout Program

Pembuatan File Pendukung

Pada file layout diatas, penulis ada menggunakan custom drawable. Jadi, silakan buat file drawable baru dengan nama background_button_keypad.xml dan isi dengan source code berikut.

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android">
    <selector>
        <item
            android:state_pressed="true"
            >
            <shape
                android:shape="rectangle"
                >
                <solid
                    android:color="#bdbdbd"
                    />
                <stroke
                    android:width="0.5dp"
                    android:color="#eeeeee"
                    />
            </shape>
        </item>
        <item>
            <shape
                android:shape="rectangle"
                >
                <solid
                    android:color="@android:color/transparent"
                    />
                <stroke
                    android:width="0.5dp"
                    android:color="#e0e0e0"
                    />
            </shape>
        </item>
    </selector>
</inset>

MainActivity.kt

Di dalam file MainActivity.kt, penulis akan menjelaskan beberapa syntax baru yang mungkin pembaca belum tahu apa itu fungsinya. Jadi, saya akan menyampaikannya secara per kode ya.

Penulisan Package Name dan Import Library

package com.ysn.belajarkotlinextension

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import kotlinx.android.synthetic.main.activity_main.*

Penjelasan: Dalam Kotlin, penulisan package name dan import library hampir sama bahkan sama persis seperti di Java jadi, tidak ada perbedaannya ya. Oya, pada kode diatas ada melakukan import library kotlin extension loh. Itu loh yang ini import kotlinx.android.synthetic.main.activity_main.*

Penulisan Nama Class, Extends dan Implements

class MainActivity : AppCompatActivity(), View.OnClickListener

Penjelasan: Dalam Kotlin, penulisan kelas diawali dengan keyword class kemudian dilanjutkan dengan nama kelasnyanya. Kemudian, untuk melakukan extends dan implements dari kelas tersebut maka, di Kotlin Anda bisa menggunakan tanda titik dua ( : ). Seperti yang Anda lihat diatas, bahwa kita ada melakukan extends kelas ke AppCompatActivity dan implements ke View.OnClickListener

Penulisan Nama Variable dan Object

private val TAG: String = "MainActivityTAG"
private var arrayUnitTemperature: Array<String>? = null
private var temperature: String = "0"

Penjelasan: Dalam Kotlin, penulisan nama variable harus diawali dengan nama variable-nya baru dilanjutkan dengan tipe datanya atau langsung diinisialisasikan juga bisa. Ada 2 tipe penulisan variable di Kotlin yakni, menggunakan keyword val dan var. Perbedaannya adalah val untuk nilai konstan atau read only sementara var untuk nilai yang dapat diubah. Kemudian, disitu juga bisa Anda lihat ada operator ? yang mana dalam Kotlin ini ada 2 tipe yakni, !! dan ?. Perbedaannya adalah !! untuk mengeksekusi sebuah variable apabila nilainya non-null maupun null sedangkan, ? untuk mengeksekusi sebuah variable apabila nilainya non-null saja jadi, jelas lebih bagus ini karena bisa mencegah NPE atau Null Pointer Exception

Penulisan Method/Function

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initComponent()
}

Penjelasan: Dalam Kotlin, penulisan method atau function harus menggunakan keyword fun kemudian dilanjutkan dengan nama method atau function nya. Dan apabila method atau function tersebut mempunyai return value maka, setelah tanda tutup kurung diberi tanda titik dua dan dilanjutkan dengan tipe datanya. Contoh:

fun hitung(nilai1: Int, nilai2: Int): Int {
        return nilai1.plus(nilai2)
}

Penulisan Fungsi initComponent

private fun initComponent() {
        arrayUnitTemperature = arrayOf("C", "F", "K", "R", "Re")
        val arrayUnitDescribeTemperature = arrayOf("Celcius", "Fahrenheit", "Kelvin", "Rankine", "Reaumur")
        val arrayAdapterUnitTemperature = ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, arrayUnitTemperature)
        app_compat_spinner_unit_temperature_from_activity_main.adapter = arrayAdapterUnitTemperature
        app_compat_spinner_unit_temperature_to_activity_main.adapter = arrayAdapterUnitTemperature
        app_compat_spinner_unit_temperature_to_activity_main.setSelection(1)
        text_view_unit_temperature_to_activity_main.text = "Fahrenheit"

        button_keypad_0_activity_main.setOnClickListener(this)
        button_keypad_1_activity_main.setOnClickListener(this)
        button_keypad_2_activity_main.setOnClickListener(this)
        button_keypad_3_activity_main.setOnClickListener(this)
        button_keypad_4_activity_main.setOnClickListener(this)
        button_keypad_5_activity_main.setOnClickListener(this)
        button_keypad_6_activity_main.setOnClickListener(this)
        button_keypad_7_activity_main.setOnClickListener(this)
        button_keypad_8_activity_main.setOnClickListener(this)
        button_keypad_9_activity_main.setOnClickListener(this)
        button_keypad_backspace_activity_main.setOnClickListener(this)
        button_keypad_ac_activity_main.setOnClickListener(this)
        button_keypad_dot_activity_main.setOnClickListener(this)
        button_keypad_plus_minus_activity_main.setOnClickListener(this)

        app_compat_spinner_unit_temperature_from_activity_main.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(p0: AdapterView<*>?) {
                // nothing to do in here
            }

            override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, index: Int, id: Long) {
                text_view_unit_temperature_from_activity_main.text = arrayUnitDescribeTemperature.get(index)
                if (temperature != "0" && temperature != "0.0") {
                    calculateTemperatureConversion()
                }
            }

        }
        app_compat_spinner_unit_temperature_to_activity_main.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(p0: AdapterView<*>?) {
                // nothing to do in here
            }

            override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, index: Int, id: Long) {
                text_view_unit_temperature_to_activity_main.text = arrayUnitDescribeTemperature.get(index)
                if (temperature != "0" && temperature != "0.0") {
                    calculateTemperatureConversion()
                }
            }

        }
    }

Penjelasan: Dalam kode diatas, kita ada mendeklarasikan sebuah array dengan nilainya String(C, F, R, Re). Kemudian, ada pendeklarasian array lagi untuk kepanjangan dari setiap singkatan suhu yang dideklarasikan sebelumnya pada variable arrayUnitDescribeTemperature. Selain itu, pada kode diatas, penulis ada mendeklarasikan adapter untuk spinner untuk app_compat_spinner_unit_temperature_from_activity_main dan app_compat_spinner_unit_temperature_to_activity_main. Selanjutnya, kita ada memberikan listener onclick ke semua Button yang ada. Dan listener onItemSelected untuk komponen app_compat_spinner_unit_temperature_from_activity_main dan app_compat_spinner_unit_temperature_to_activity_main.

Method Listener OnClick

override fun onClick(view: View?) {
        when (view?.id) {
            R.id.button_keypad_0_activity_main -> {
                updateTemperatureValueFrom("0")
            }
            R.id.button_keypad_1_activity_main -> {
                updateTemperatureValueFrom("1")
            }
            R.id.button_keypad_2_activity_main -> {
                updateTemperatureValueFrom("2")
            }
            R.id.button_keypad_3_activity_main -> {
                updateTemperatureValueFrom("3")
            }
            R.id.button_keypad_4_activity_main -> {
                updateTemperatureValueFrom("4")
            }
            R.id.button_keypad_5_activity_main -> {
                updateTemperatureValueFrom("5")
            }
            R.id.button_keypad_6_activity_main -> {
                updateTemperatureValueFrom("6")
            }
            R.id.button_keypad_7_activity_main -> {
                updateTemperatureValueFrom("7")
            }
            R.id.button_keypad_8_activity_main -> {
                updateTemperatureValueFrom("8")
            }
            R.id.button_keypad_9_activity_main -> {
                updateTemperatureValueFrom("9")
            }
            R.id.button_keypad_backspace_activity_main -> {
                backspaceTemperatureValueFrom()
            }
            R.id.button_keypad_ac_activity_main -> {
                clearTemperatureValueFrom()
            }
            R.id.button_keypad_dot_activity_main -> {
                updateTemperatureValueFrom(".")
            }
            R.id.button_keypad_plus_minus_activity_main -> {
                changePlusMinusValueFrom()
            }
            else -> {
                // nothing to do in here
            }
        }
}

Penjelasan: Diatas merupakan method listener onclick yang berbentuk implements dari class. Kemudian, didalam method tersebut ada keyword when yang mana dalam Java ini merupakan switch. Jadi, R.id.button_keypad_0_activity_main -> ini merupakan case untuk setiap item yang ada. Dan else pada bagian akhir merupakan default pada switch jika di Java.

Pembuatan Method Logic Konversi Suhu

private fun changePlusMinusValueFrom() {
        if (temperature.startsWith("-")) {
            temperature = temperature.replace("-", "")
        } else {
            temperature = "-$temperature"
        }
        temperature = if (temperature == "-0") "0" else temperature
        text_view_value_temperature_from_activity_main.text = temperature
    }

    private fun clearTemperatureValueFrom() {
        temperature = "0"
        text_view_value_temperature_from_activity_main.text = temperature
        text_view_value_temperature_to_activity_main.text = "0"
    }

    private fun backspaceTemperatureValueFrom() {
        if (temperature != "0") {
            temperature = temperature.substring(0, temperature.length - 1)
        }
        temperature = if (temperature.isEmpty() || temperature == "-") "0" else temperature
        text_view_value_temperature_from_activity_main.text = temperature
        if (temperature == "0" || temperature == "0.0") {
            text_view_value_temperature_to_activity_main.text = "0"
        }
    }

    private fun updateTemperatureValueFrom(strValue: String) {
        if (strValue == "0") {
            temperature = if (temperature == "0") "0" else temperature.plus(strValue)
        } else if (strValue == ".") {
            temperature = if (!temperature.contains(".")) temperature.plus(strValue) else temperature
        } else {
            temperature = if (temperature == "0") strValue else temperature.plus(strValue)
        }
        Log.d(TAG, "temperature: $temperature")
        text_view_value_temperature_from_activity_main.text = temperature
        if (temperature != "0" && temperature != "0.0") {
            calculateTemperatureConversion()
        } else {
            text_view_value_temperature_to_activity_main.text = "0"
        }
    }

    private fun calculateTemperatureConversion() {
        val unitTemperatureFrom = app_compat_spinner_unit_temperature_from_activity_main.selectedItem.toString()
        val unitTemperatureTo = app_compat_spinner_unit_temperature_to_activity_main.selectedItem.toString()
        Log.d(TAG, "unitTemperatureTo: $unitTemperatureTo")
        val temperatureFrom = temperature.toDouble()
        var temperatureTo: Double = 0.0
        Log.d(TAG, "temperatureFrom: $temperatureFrom && temperatureTo: $temperatureTo && unitTemperatureFrom: $unitTemperatureFrom && unitTemperatureTo: $unitTemperatureTo")

        if (unitTemperatureFrom == "C") {
            when (unitTemperatureTo) {
                "F" -> {
                    // C x 1,8 + 32
                    temperatureTo = temperatureFrom.times(1.8).plus(32)
                    Log.d(TAG, "temperatureTo new: $temperatureTo")
                }
                "K" -> {
                    // C + 273,15
                    temperatureTo = temperatureFrom.plus(273.15)
                }
                "R" -> {
                    // 1,8 x (C + 496,67)
                    temperatureTo = (temperatureFrom.plus(496.67)).times(1.8)
                }
                "Re" -> {
                    // C x 0,8
                    temperatureTo = temperatureFrom.times(0.8)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "F") {
            when (unitTemperatureTo) {
                "C" -> {
                    // (F - 32) / 1,8
                    temperatureTo = (temperatureFrom.minus(32)).div(1.8)
                }
                "K" -> {
                    // (F + 459,67) / 1,8
                    temperatureTo = (temperatureFrom.plus(459.67)).div(1.8)
                }
                "R" -> {
                    // F + 459,67
                    temperatureTo = temperatureFrom.plus(459.67)
                }
                "Re" -> {
                    // (F - 32) / 2,25
                    temperatureTo = (temperatureFrom.minus(32)).div(2.25)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "K") {
            when (unitTemperatureTo) {
                "C" -> {
                    // K - 273,15
                    temperatureTo = temperatureFrom.minus(273.15)
                }
                "F" -> {
                    // K x 1,8 - 459,67
                    temperatureTo = temperatureFrom.times(1.8).minus(459.67)
                }
                "R" -> {
                    // K x 1,8
                    temperatureTo = temperatureFrom.times(1.8)
                }
                "Re" -> {
                    // (K - 273,15) x 0,8
                    temperatureTo = (temperatureFrom.minus(273.15)).div(0.8)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "R") {
            when (unitTemperatureTo) {
                "C" -> {
                    // R / 1,8 + 273,15
                    temperatureTo = temperatureFrom.div(1.8).plus(273.15)
                }
                "F" -> {
                    // R - 459,67
                    temperatureTo = temperatureFrom.minus(459.67)
                }
                "K" -> {
                    // R / 1,8
                    temperatureTo = temperatureFrom.div(1.8)
                }
                "Re" -> {
                    // (R / 1,8 + 273,15) x 0,8
                    temperatureTo = temperatureFrom.div(1.8).plus(273.15).times(0.8)
                }
                else -> {
                    // nothing to do in here
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "Re") {
            when (unitTemperatureTo) {
                "C" -> {
                    // Re / 0,8
                    temperatureTo = temperatureFrom.div(0.8)
                }
                "F" -> {
                    // Re x 2,25 + 32
                    temperatureTo = temperatureFrom.times(2.25).plus(32)
                }
                "K" -> {
                    // Re / 0,8 + 273,15
                    temperatureTo = temperatureFrom.div(0.8).plus(273.15)
                }
                "R" -> {
                    // Re x 2,25 + 491,67
                    temperatureTo = temperatureFrom.times(2.25).plus(491.67)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        }
        text_view_value_temperature_to_activity_main.text = temperatureTo.toString()
}

Penjelasan: Pada method changePlusMinusValueFrom berfungsi untuk mengubah nilai negatif menjadi positif dan sebaliknya. Kemudian, pada method clearTemperatureValueFrom berfungsi untuk meng-set semua nilai di view kembali ke semula atau nol. Method backspaceTemperatureValueFrom berfungsi untuk menghapus satu karakter diakhir pada nilai yang mau dikonversi karena, pada app inputan dilakukan menggunakan button angka yang tersedia bukan menggunakan soft keyboard. Selanjutnya method updateTemperatureValueFrom berfungsi untuk melakukan update atau eksekusi lakukan proses konversi suhu apabila nilainya berubah karena, pada app tidak ada button sama dengan jadi, proses konversi berjalan secara listener. Dan yang terakhir adalah method calculateTemperatureConversion yang ini berguna untuk melakukan proses konversi dari suatu suhu tertentu menjadi suhu lain.

Kode Lengkap MainActivity.kt

package com.ysn.belajarkotlinextension

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), View.OnClickListener {

    private var TAG: String = "MainActivityTAG"
    private var arrayUnitTemperature: Array<String>? = null
    private var temperature: String = "0"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initComponent()
    }

    private fun initComponent() {
        arrayUnitTemperature = arrayOf("C", "F", "K", "R", "Re")
        val arrayUnitDescribeTemperature = arrayOf("Celcius", "Fahrenheit", "Kelvin", "Rankine", "Reaumur")
        val arrayAdapterUnitTemperature = ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, arrayUnitTemperature)
        app_compat_spinner_unit_temperature_from_activity_main.adapter = arrayAdapterUnitTemperature
        app_compat_spinner_unit_temperature_to_activity_main.adapter = arrayAdapterUnitTemperature
        app_compat_spinner_unit_temperature_to_activity_main.setSelection(1)
        text_view_unit_temperature_to_activity_main.text = "Fahrenheit"

        button_keypad_0_activity_main.setOnClickListener(this)
        button_keypad_1_activity_main.setOnClickListener(this)
        button_keypad_2_activity_main.setOnClickListener(this)
        button_keypad_3_activity_main.setOnClickListener(this)
        button_keypad_4_activity_main.setOnClickListener(this)
        button_keypad_5_activity_main.setOnClickListener(this)
        button_keypad_6_activity_main.setOnClickListener(this)
        button_keypad_7_activity_main.setOnClickListener(this)
        button_keypad_8_activity_main.setOnClickListener(this)
        button_keypad_9_activity_main.setOnClickListener(this)
        button_keypad_backspace_activity_main.setOnClickListener(this)
        button_keypad_ac_activity_main.setOnClickListener(this)
        button_keypad_dot_activity_main.setOnClickListener(this)
        button_keypad_plus_minus_activity_main.setOnClickListener(this)

        app_compat_spinner_unit_temperature_from_activity_main.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(p0: AdapterView<*>?) {
                // nothing to do in here
            }

            override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, index: Int, id: Long) {
                text_view_unit_temperature_from_activity_main.text = arrayUnitDescribeTemperature.get(index)
                if (temperature != "0" && temperature != "0.0") {
                    calculateTemperatureConversion()
                }
            }

        }
        app_compat_spinner_unit_temperature_to_activity_main.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(p0: AdapterView<*>?) {
                // nothing to do in here
            }

            override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, index: Int, id: Long) {
                text_view_unit_temperature_to_activity_main.text = arrayUnitDescribeTemperature.get(index)
                if (temperature != "0" && temperature != "0.0") {
                    calculateTemperatureConversion()
                }
            }

        }
    }

    override fun onClick(view: View?) {
        when (view?.id) {
            R.id.button_keypad_0_activity_main -> {
                updateTemperatureValueFrom("0")
            }
            R.id.button_keypad_1_activity_main -> {
                updateTemperatureValueFrom("1")
            }
            R.id.button_keypad_2_activity_main -> {
                updateTemperatureValueFrom("2")
            }
            R.id.button_keypad_3_activity_main -> {
                updateTemperatureValueFrom("3")
            }
            R.id.button_keypad_4_activity_main -> {
                updateTemperatureValueFrom("4")
            }
            R.id.button_keypad_5_activity_main -> {
                updateTemperatureValueFrom("5")
            }
            R.id.button_keypad_6_activity_main -> {
                updateTemperatureValueFrom("6")
            }
            R.id.button_keypad_7_activity_main -> {
                updateTemperatureValueFrom("7")
            }
            R.id.button_keypad_8_activity_main -> {
                updateTemperatureValueFrom("8")
            }
            R.id.button_keypad_9_activity_main -> {
                updateTemperatureValueFrom("9")
            }
            R.id.button_keypad_backspace_activity_main -> {
                backspaceTemperatureValueFrom()
            }
            R.id.button_keypad_ac_activity_main -> {
                clearTemperatureValueFrom()
            }
            R.id.button_keypad_dot_activity_main -> {
                updateTemperatureValueFrom(".")
            }
            R.id.button_keypad_plus_minus_activity_main -> {
                changePlusMinusValueFrom()
            }
            else -> {
                // nothing to do in here
            }
        }
    }

    private fun changePlusMinusValueFrom() {
        // do something
        if (temperature.startsWith("-")) {
            temperature = temperature.replace("-", "")
        } else {
            temperature = "-$temperature"
        }
        temperature = if (temperature == "-0") "0" else temperature
        text_view_value_temperature_from_activity_main.text = temperature
    }

    private fun clearTemperatureValueFrom() {
        temperature = "0"
        text_view_value_temperature_from_activity_main.text = temperature
        text_view_value_temperature_to_activity_main.text = "0"
    }

    private fun backspaceTemperatureValueFrom() {
        if (temperature != "0") {
            temperature = temperature.substring(0, temperature.length - 1)
        }
        temperature = if (temperature.isEmpty() || temperature == "-") "0" else temperature
        text_view_value_temperature_from_activity_main.text = temperature
        if (temperature == "0" || temperature == "0.0") {
            text_view_value_temperature_to_activity_main.text = "0"
        }
    }

    private fun updateTemperatureValueFrom(strValue: String) {
        if (strValue == "0") {
            temperature = if (temperature == "0") "0" else temperature.plus(strValue)
        } else if (strValue == ".") {
            temperature = if (!temperature.contains(".")) temperature.plus(strValue) else temperature
        } else {
            temperature = if (temperature == "0") strValue else temperature.plus(strValue)
        }
        Log.d(TAG, "temperature: $temperature")
        text_view_value_temperature_from_activity_main.text = temperature
        if (temperature != "0" && temperature != "0.0") {
            calculateTemperatureConversion()
        } else {
            text_view_value_temperature_to_activity_main.text = "0"
        }
    }

    private fun calculateTemperatureConversion() {
        val unitTemperatureFrom = app_compat_spinner_unit_temperature_from_activity_main.selectedItem.toString()
        val unitTemperatureTo = app_compat_spinner_unit_temperature_to_activity_main.selectedItem.toString()
        Log.d(TAG, "unitTemperatureTo: $unitTemperatureTo")
        val temperatureFrom = temperature.toDouble()
        var temperatureTo: Double = 0.0
        Log.d(TAG, "temperatureFrom: $temperatureFrom && temperatureTo: $temperatureTo && unitTemperatureFrom: $unitTemperatureFrom && unitTemperatureTo: $unitTemperatureTo")

        if (unitTemperatureFrom == "C") {
            when (unitTemperatureTo) {
                "F" -> {
                    // C x 1,8 + 32
                    temperatureTo = temperatureFrom.times(1.8).plus(32)
                    Log.d(TAG, "temperatureTo new: $temperatureTo")
                }
                "K" -> {
                    // C + 273,15
                    temperatureTo = temperatureFrom.plus(273.15)
                }
                "R" -> {
                    // 1,8 x (C + 496,67)
                    temperatureTo = (temperatureFrom.plus(496.67)).times(1.8)
                }
                "Re" -> {
                    // C x 0,8
                    temperatureTo = temperatureFrom.times(0.8)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "F") {
            when (unitTemperatureTo) {
                "C" -> {
                    // (F - 32) / 1,8
                    temperatureTo = (temperatureFrom.minus(32)).div(1.8)
                }
                "K" -> {
                    // (F + 459,67) / 1,8
                    temperatureTo = (temperatureFrom.plus(459.67)).div(1.8)
                }
                "R" -> {
                    // F + 459,67
                    temperatureTo = temperatureFrom.plus(459.67)
                }
                "Re" -> {
                    // (F - 32) / 2,25
                    temperatureTo = (temperatureFrom.minus(32)).div(2.25)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "K") {
            when (unitTemperatureTo) {
                "C" -> {
                    // K - 273,15
                    temperatureTo = temperatureFrom.minus(273.15)
                }
                "F" -> {
                    // K x 1,8 - 459,67
                    temperatureTo = temperatureFrom.times(1.8).minus(459.67)
                }
                "R" -> {
                    // K x 1,8
                    temperatureTo = temperatureFrom.times(1.8)
                }
                "Re" -> {
                    // (K - 273,15) x 0,8
                    temperatureTo = (temperatureFrom.minus(273.15)).div(0.8)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "R") {
            when (unitTemperatureTo) {
                "C" -> {
                    // R / 1,8 + 273,15
                    temperatureTo = temperatureFrom.div(1.8).plus(273.15)
                }
                "F" -> {
                    // R - 459,67
                    temperatureTo = temperatureFrom.minus(459.67)
                }
                "K" -> {
                    // R / 1,8
                    temperatureTo = temperatureFrom.div(1.8)
                }
                "Re" -> {
                    // (R / 1,8 + 273,15) x 0,8
                    temperatureTo = temperatureFrom.div(1.8).plus(273.15).times(0.8)
                }
                else -> {
                    // nothing to do in here
                    temperatureTo = temperatureFrom
                }
            }
        } else if (unitTemperatureFrom == "Re") {
            when (unitTemperatureTo) {
                "C" -> {
                    // Re / 0,8
                    temperatureTo = temperatureFrom.div(0.8)
                }
                "F" -> {
                    // Re x 2,25 + 32
                    temperatureTo = temperatureFrom.times(2.25).plus(32)
                }
                "K" -> {
                    // Re / 0,8 + 273,15
                    temperatureTo = temperatureFrom.div(0.8).plus(273.15)
                }
                "R" -> {
                    // Re x 2,25 + 491,67
                    temperatureTo = temperatureFrom.times(2.25).plus(491.67)
                }
                else -> {
                    temperatureTo = temperatureFrom
                }
            }
        }
        text_view_value_temperature_to_activity_main.text = temperatureTo.toString()
    }
}

Output

Output Projek

Semua projek pada tutorial ini sudah penulis upload ke Github

CodePolitan Developer School

Saat ini CodePolitan mengadakan program pelatihan belajar coding intensif merupakan Solusi belajar pemrograman Basic Android yang berorientasi pada kebutuhan industri selama satu minggu secara tatap muka dengan bimbingan mentor berpengalaman yang dilengkapi dengan fasilitas asrama selama belajar.

Benefit apa yang bisa kamu dapatkan dari CodePolitan Developer School?

  • Belajar Intensif selama seminggu dan dibimbing mentor berpengalaman
  • Program Karantina untuk mendapatkan hasil yang maksimal
  • Kurikulum belajar disusun sesuai dengan kebutuhan industri
  • Modul belajar dari Google Android Developer Fundamentals
  • Konsultasi Belajar dengan mentor setelah program
  • Mendapatkan kemampuan basic sebagai pondasi menjadi Android Developer

Yuk gabung dengan CodePolitan Developer School buat aplikasi Androidmu dalam 1 minggu dan mulai karirmu sebagai Android Developer dengan mendapatkan semua manfaat di atas :)

Baca juga artikel Android menarik lainnya coder :