본문 바로가기

책/오준석의 안드로이드 생존코딩 코틀린편

5. 비만도 계산기

프로젝트명 BmiCalculator
기능
  • 키와 몸무게를 임력 하고 결과 버튼을 누르면 다른 화면에서도 비반도 결과를 문자와 그림으로 보여줍니다.
  • 마지막에 입력했던 키와 몸무게는 자동으로 저장됩니다.
핵심구성요소
  • ConstraintLayout: 제약에 따라 뷰를 배치하는 레이아웃 입니다.
  • Intent: 화면을 전환에 사용하고, 간단한 데이터를 전달할 수 있습니다.
  • SharedPreference: 간단한 데이터를 저장할 수 있습니다.
라이브러리 설정 Anko : 인텐트, 다이얼로그, 로그 등을 구현하는 데 도움이 되는 라이브러리 
  1. 준비하기 : 프로젝트 생성 및 안드로이드 설정
  2. 스텝1 : 키와 몸무게를 입력하는 화면 작성
  3. 스텝2 : 결과 화면 작성
  4. 스텝3 : 인텐트로 화면 전환
  5. 스텝4 : SharedPreference로 데이터를 저장하기

준비하기

Anko 라이브러리 사용준비

  • Anko Commons: 인텐트, 다이얼로그, 로그 등을 편리하게 사용하는 라이브러리
  • Anko Layouts: 안드로이드 레이아웃을 코드로 쉽게 작성하는 라이브러리
  • Anko SQLite: SQLite를 쉽게 사용하는 라이브러리
  • Anko Corutines: 코루틴을 쉽게 사용하는 라이브러리

참고 : https://github.com/Kotlin/anko 

 

Kotlin/anko

Pleasant Android application development. Contribute to Kotlin/anko development by creating an account on GitHub.

github.com

Anko 라이브러리 (Anko Commons) 를 다음과 같이 추가하고  Sync Now를 클릭한다.

 

./app/build.gradle

dependencies { 
....
    implementation "org.jetbrains.anko:anko:$anko_version"
....
}

 

./build.gradle

buildscript {
....
    ext.anko_version = "0.10.5"
....
}

스텝1 키와 몸무게를 입력하는 화면 작성

activity_main.xml 레이아웃의 화면을 다음과 같이 작성한다.

스텝2 결과 화면 작성

File -> New -> Activity -> Empty Activity 클릭 후 다음과 같이 작성

activity_result.xml 레이아웃의 화면을 다음과 같이 작성한다.

프로젝트 창에서 res폴더에서 우클릭 -> New -> Vector Asset을 클릭하고 다음과 선택한다.

같은 방법으로 비만, 저체중일때 아이콘을 추가한다. 

activity_result.xml 레이아웃에서 ImageView를 생성 선택하고, Attribute 속성에서 검색 아이콘 클릭 tint를 검색해여 다음과 같이 색상을 변경한다.

벡터 드로어블 사용 환경

위의 이미지는 벡터 이미지로 벡터 드로어블 리소스로 분류 된다. 안드로이드 5.0이상에서 동작하는데 그 미만의 기기에서도 동작하게 하려면 다음과 같이 .app/build.gradle파일에 다음을 추가하여야 한다. 

android {
....
    defaultConfig {
....
        vectorDrawables.useSupportLibrary = true
    }
....
}

스텝3 인텐트로 화면 전환

버튼을 누르면 결과 화면으로 전환하는 코드 작성

package junsuk.example.bmicalculator

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        resultButton.setOnClickListener {
            /*
            val intent = Intent(this, ResultActivity::class.java)
            startActivity(intent)
            */

            // Anko 라이브러리를 적용한 코틀린의 액티비티 전환코드
            startActivity<ResultActivity>()
        }

    }
}

이전 화면으로 돌아가는 업 네비게이션

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="junsuk.example.bmicalculator">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!-- 
        이렇게 parentActivityName 속성에 상위 액티비티를 지정하면 간단히 상하관계를 지정할 수 있다.
        ResultActivity 에서 뒤로가기를 누르면 이전 액티비티(MainActivity)로 잘 이동된다.
        -->
        <activity android:name=".ResultActivity"
                  android:parentActivityName=".MainActivity"
            >
        </activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

인텐트에 데이터를 담기

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        resultButton.setOnClickListener {
            /*
            val intent = Intent(this, ResultActivity::class.java)
            intent.putExtra("weight", weightEditText.text.toString())
            intent.putExtra("height", heightEditText.text.toString())
            startActivity(intent)
            */


            // Anko 라이브러리를 적용한 코틀린의 액티비티 전환코드
            startActivity<ResultActivity>(
                "weight" to weightEditText.text.toString(),
                "height" to heightEditText.text.toString()
            )
        }

    }
}

비만도를 계산 하여 분기 처리하기

package junsuk.example.bmicalculator

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_result.*
import org.jetbrains.anko.toast

class ResultActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_result)

        // 인텐트로 전달받은 키와 몸무게
        val height = intent.getStringExtra("height").toInt()
        val weight = intent.getStringExtra("weight").toInt()

        // BMI 계산
        val bmi = weight / Math.pow(height / 100.0, 2.0)

        // 결과 표시
        when {
            bmi >= 35 -> resultTextView.text = "고도 비만"
            bmi >= 30 -> resultTextView.text = "2단계 비만"
            bmi >= 25 -> resultTextView.text = "1단계 비만"
            bmi >= 23 -> resultTextView.text = "과체중"
            bmi >= 18.5 -> resultTextView.text = "정상"
            else -> resultTextView.text = "저체중"

        }

        // 이미지 표시
        when {
            bmi >= 23 -> 
                imageView.setImageResource(R.drawable.ic_baseline_sentiment_satisfied_24)
            bmi >= 18.5 -> 
                imageView.setImageResource(R.drawable.ic_baseline_sentiment_satisfied_alt_24)
            else -> 
                imageView.setImageResource(R.drawable.ic_baseline_cancel_presentation_24)
        }
        
        /*
        Toast.makeText(this,"$bmi", Toast.LENGTH_LONG).show()
        */
        // Anko를 적용한 토스트 코드
        toast("$bmi")
    }
}

스텝4 SharedPreference로 데이터 저장하기

더보기

android.preference.PreferenceManager 는 deprecated 가 되어 androidx.preference.PreferenceManager 를 import 하여 사용하여야 한다.

androidx.preference.PreferenceManager는 ./app/build.gradle 에서

implementation "androidx.preference:preference-ktx:1.1.0" 를 dependencies 에 넣어야 한다. 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //이전에 입력한 값을 읽어오기
        loadData()

        resultButton.setOnClickListener {
            /*
            val intent = Intent(this, ResultActivity::class.java)
            intent.putExtra("weight", weightEditText.text.toString())
            intent.putExtra("height", heightEditText.text.toString())
            startActivity(intent)
            */

            // 마지막에 입력한 내용 저장
            saveData(
                weightEditText.text.toString().toInt(),
                heightEditText.text.toString().toInt()
            )

            // Anko 라이브러리를 적용한 코틀린의 액티비티 전환코드
            startActivity<ResultActivity>(
                "weight" to weightEditText.text.toString(),
                "height" to heightEditText.text.toString()
            )
        }

    }

    private fun saveData(height: Int, weight: Int) {
        var pref = PreferenceManager.getDefaultSharedPreferences(this)
        var editor = pref.edit()

        editor.putInt("KEY_HEIGHT",height)
            .putInt("KEY_WEIGHT", weight)
            .apply()
    }

    private fun loadData() {

        var pref = PreferenceManager.getDefaultSharedPreferences(this)
        val height = pref.getInt("KEY_HEIGHT",0)
        val weight = pref.getInt("KEY_WEIGHT",0)

        if(height != 0 && weight != 0)
        {
            heightEditText.setText(height.toString())
            weightEditText.setText(weight.toString())
        }
    }
}

결과

' > 오준석의 안드로이드 생존코딩 코틀린편' 카테고리의 다른 글

8. 수평 측정기  (0) 2020.06.16
7. 나만의 웹 브라우저  (0) 2020.06.15
6. 스톱워치  (0) 2020.06.11
4. 코틀린  (0) 2020.06.08
3. 첫 번째 앱 만들기  (0) 2020.06.07