또는

비만도 계산기

 

기능 소개

키와 몸무게를 입력하고 결과보기 버튼을 누르면 새 화면에서 비만도를 문자와 그림으로 표시합니다.

부수 기능으로 마지막으로 입력한 키와 몸무게 자료를 저장합니다.

 

핵심이 되는 주제

입력 및 출력 두 개 화면('액티비티')을 사용합니다.

두 화면 사이에 데이터 전달은 인텐트라는 화면 전환을 사용합니다.

SharedPreference로 자료를 저장합니다.

 

기타 : Anko 라이브러리 사용 방법 ( 라이브러리 의존성 추가)

        벡터 이미지 사용 방법

실습

1) 빈 액티비티를 갖는 프로젝트 생성 (앱 이름 : BMICalculator) 

2) 코드 작성을 쉽게 해주는 Anko 라이브러리 추가 
    
참고: Anko 라이브러리의 구성 
 ① Anko Commons (인텐트, 다이얼로그, 로그)  <-- 우리가 사용할 모듈  
 ② Anko Layouts (레이아웃) 
 ③ Anko SQLite (SQLite) 
 ④ Anko Coroutines (코루틴) 

프로젝트 탐색기 창에서 모듈 수준의 그레이들 파일인 build.gradle 파일을 더블 클릭하여 편집.

 (파일명 뒤에 Module 수준과 Project 수준의 구분이 표시되어 있음)

dependencies 항목에 다음의 Anko 라이브러리를 추가.

 ('라이브러리 의존성 추가'라고 하며 안드로이드 스튜디오에서 자동 다운로드 설치를 하게 됨)

   implementation "org.jetbrains.anko:anko:$anko_version"

[ Anko 라이브러리 추가 ]

 

프로젝트 탐색기 창에서 프로젝트 수준의 그레이들 파일인 build.project 파일을 더블 클릭하여

Anko 라이브러리 버전을 변수로 지정.

 

buildscript {

    ext.kotlin_version = '1.3.50'

    ext.anko_version='0.10.5'

    repositories {

        google()

        jcenter()

       

    }

    dependencies {

    ....

    }

}

 

추가한 그레이들 파일들을 적용하기 위해 에디트창 탭 이름 바로 아래에 'Sync Now'를 클릭해서

프로젝트를 재 빌드.

 

 

3) 레이아웃 작업 1 - , 몸무게 입력 화면

 

'Plain Text' 배치

  ID : heightEditText

  input Type : (숫자만 입력할 있도록) number

  hint : (입력 전에 표시할 문자열) (cm)  --> 문자열이 보이도록 text 란의 Name 삭제

 

Plain Text 뷰도 되지만, 숫자만 입력할 거니까 이번에는 'Number' 뷰를 배치

  ID : weightEditText

 

'Button' 배치

  ID : resultButton

[ 입력 화면 ]

 

 

4) 레이아웃 작업 2 - 결과 화면

에디터 창을 디자인이 아닌 텍스트 모드로 전환한 후, 결과를 출력할 새로운 액티비티 추가.
  File > New > Activity > Empty Activity
  (Activity Name : ResultActivity)

① activity_result.xml 창에 TextView 뷰 배치
   ID : resultTextView
   textAppearance : appCompat.Large

[ 결과 화면 ]

② 이미지 뷰 배치
  
  참고) 안드로이드 스튜디오에서 제공하는 이미지 파일들
    비트맵 이미지: PNG, JPG
    벡터 이미지 : SVG, EPS

   벡터 이미지를 사용해 보자. (에셋 스튜디오에서 생성할 있음)
      프로젝트 창 > res 폴더 우클릭 > New > Vector Asset에서 벡터 이미지 생성
      Clip Art: 에서 원하는 이미지 선택
   같은 방법으로 비만도 정상, 비만, 저체중 세 가지 이미지를 추가.

   
activity_result.xml 화면에서 ImageView 뷰를 배치
   project 항목에서 '정상'용 이미지를 선택하고 OK   (: 스마일 아이콘)
   ImageView 속성 : 사이즈 조정 (: 가로(layout_width), 세로(layout_height : 각각 100 dp),

                         색상(tint) 조정
   
※ 벡터 이미지는 vectorDrawable 리소스로 분류하는데,

   백터드로어블은 Android 5.0부터 동작함.
   우리는 4.4버전으로 생성했으므로 모듈 수준의 build.gradle 파일에

  다음을 추가해 이를 지원케 해야 함. (Sync Now 잊지말고!)

    defaultConfig {
       vectorDrawables.useSupportLibrary = true
    }

[ 결과 화면 ]

 


5) 뒤로가기 기능 추가

 

결과 화면에서 다시 입력화면으로 돌아가기 위한, '뒤로가기' 기능을 상단에 추가해 보죠.

 

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

    <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">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

앱을 실행해 보면, 결과화면 상단에 뒤로가기 링크가 표시되고, 터치하면 입력 화면으로 되돌아 갑니다.

[ 뒤로가기 링크 ]

 

 


6) 코딩

간단한 데이터와 함께 다른 화면(액티비티) 구동해 주는 인텐트를 이용합니다.

 

  

 

<< 자료 입력 화면 MainActivity >>

-- MainActivity.kt (코틀린 일반 코딩)

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.content.Intent     // 자동으로 임포트됨
import kotlinx.android.synthetic.main.activity_main.*  // 레이아웃 정보가 자동으로 임포트되어 있음
                                // 이 덕택에 앞에서 추가했던 텍스트뷰나 버튼 사용이 가능한 것임
                                // 자동 임포트는 'kotlin-android-extensions' 플러그인에 의한 기능임

class MainActivity : AppCompatActivity() { 

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

        loadData()

        resultButton.setOnClickListener { 
            saveData(heightEditText.text.toString().toInt(), weightEditText.text.toString().toInt())
                    
            val intt = Intent(this, ResultActivity::class.java) 
            startActivity(intt) 
        } 
    } 
    
    // SharedPreference로 자료 저장
    private fun saveData(h: Int, w: Int) {
        val pref = PreferenceManager.getDefaultSharedPreferences(this)   // 프리퍼런스 객체 생성
        val editor = pref.edit()         // 에디터 객체 얻어오기
                                     // 에디터 객체는 프리퍼런스 객체에 데이터를 넣어주는 역할을 함

        editor.putInt("HEIGHT",  h)            // 키-값 쌍으로 자료 저장
             .putInt("WEIGHT", w)
             .apply()                        // 적용
    }

    // 자료 읽어 오기
    private fun loadData() {
        val pref = PreferenceManager.getDefaultSharedPreferences(this)   // 프리퍼런스 객체 생성
        val h = pref.getInt("HEIGHT", 0)    // 0은 값이 없을 때의 디폴트 설정 값
        val w = pref.getInt("WEIGHT", 0)

        if (h !=0 && w!=0) {
            heightEditText.setText(h.toString())
            weightEditText.setText(w.toString())
        }
    }

} 

 

 

-- MainActivity.kt (Anko 코딩)

 

우리는 Anko 라이브러리를 추가해서 빌드하고 있는데, Anko 라이브러리를 경우 버튼 리스너

다음과 같이 간결하게 적어도 됩니. (, anko 라이브러리를 임포트해 줘야 )

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity   // 추가할 것

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        
        resultButton.setOnClickListener {
            saveData(heightEditText.text.toString().toInt(), weightEditText.text.toString().toInt())

            // Anko 코딩된 부분
            startActivity<ResultActivity>(
                "weight" to weightEditText.text.toString(),
                "height" to heightEditText.text.toString()
            ) 
        }
    }

    ...
}

 

 

<< 결과 화면 ResultActivity >>

 

-- ResultActivity.kt onCreate()

 

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

class ResultActivity : AppCompatActivity() {

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

        val h = intent.getStringExtra("height").toInt()      // 인텐트에서 자료 빼오기
        val w = intent.getStringExtra("weight").toInt()
        val bmi = w / Math.pow(h / 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_sentiment_very_dissatisfied_black_24dp)
            bmi >= 18.5 -> imageView.setImageResource(R.drawable.ic_sentiment_satisfied_black_24dp)
            else -> imageView.setImageResource(R.drawable.ic_sentiment_dissatisfied_black_24dp)
        }

        Toast.makeText(this, "BMI : $bmi", Toast.LENGTH_SHORT).show()  // Toast 메시지로 BMI 값 출력
                                                                    // Anko로는 toast("BMI : $bmi")
}

 

 

실행 결과

  [ 입력 화면 ]
[ 결과 화면 ]

 

 

Anko 라이브러리를 추가하며 실습해 봤던, 깃허브를 이용한 '라이브러리 의존성 추가'는 참 편리하고 효과적인 것 같습니다.

 

이 번 실습을 두 세 차례 차근 차근 따라해 보면, 흐름이 파악되실 거예요. 이렇게해서 첫 번째 안드로이드 앱을 만들어 봤습니다. 수고 하셨습니다~

 

 

<<< 이전 글 보기      다음 글 보기 >>>

 

 

 

 

+ Recent posts