Develop/Kotlin

[Kotlin] 계산기 - XML 사용법과 UI 생성법 배우기

dawonny 2022. 10. 30. 22:28
728x90
반응형

ref : Udemy [Android 12 및 Kotlin 개발 완전 정복] 섹션 7


linearlayout 이란

뷰를 수평이나 수직으로 배치할 수 있는 레이아웃.

orientation 속성을 통해서 배치 방향을 결정할 수 있다.

vertical 로 설정하면 하위뷰들을 수직방향으로 배치하고

horizontal 로 설정하면 하위뷰들을 수평방향으로 배치한다.

아이템들을 수평방향으로 정렬하려면 위와 같이 orientation을 horizontal로, 수직을 원한다면 vertical 로 설정


layout_weight 속성이란

자식 뷰에 가중치를 지정해서 그 비율만큼의 자식 뷰의 크기를 지정하는 속성.

상위 뷰 그룹 하나와 

그 밑에 하위 뷰 3개로 이루어진 화면이다.

layout_weight 를 각각 1,2,3 으로 부여했을 때 다음과 같이 나타낼 수 있다.


문자열을 넣고 싶을 때

이런건 하드코딩에 해당

따라서 strings.xml 같은 파일에 따로 담는 것이 좋다.

 


계산기 UI

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:background="@color/light_grey"
        android:padding="10dp"
        android:text="@string/calc_text"
        android:textSize="48sp"
        android:gravity="end|bottom"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnSeven"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_7"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnEight"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_8"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnNine"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_9"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnDivide"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/Devide"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnFour"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_4"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnFive"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_5"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnSix"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_6"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnMultiply"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/multiply"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnOne"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_1"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnTwo"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_2"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnThree"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/_3"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnSubtract"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/subtract"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnZero"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:onClick="onDigit"
            android:text="@string/_0"/>

        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnCLR"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/clr"/>
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnAdd"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="@string/plus"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:layout_margin="2dp"
            android:id="@+id/btnEqual"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:onClick="onDigit"
            android:text="@string/equal"/>


    </LinearLayout>


</LinearLayout>

Linear Layout 을 통해 구성했다. 

0과 같은 경우에는 weight을 2로 설정해줘서 간격을 맞춰줬다.

주요 색과 같은 경우에는 values 폴더에 themes 에서 따로 회색으로 변경해주었다.


이 프로젝트에서 소수점 기능은 어떻게 만들까?

 Main.kt file 에 onDecimalPoint 라는 메소드를 하나 생성해둔 다음에 이 메소드를 호출함으로써 구현한다.

class MainActivity : AppCompatActivity() {

    var lastNumeric: Boolean = false
    var lastDot: Boolean = false 
	


   private var tvInput:TextView?=null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tvInput = findViewById(R.id.tvInput)
    }

    fun onDigit(view: View){
     tvInput?.append((view as Button).text)
        lastNumeric = true
    }

    fun onClear(view: View){
    tvInput?.text = ""
        lastNumeric = false
        lastDot = false
    }

    fun onDecimalPoint(view: View)
    {
        if (lastNumeric && !lastDot) {
            tvInput?.append(".")
            lastNumeric = false // Update the status(flag)
            lastDot = true // Update the flag
        }
    }

 

핵심은 마지막은 숫자로 끝난다는 것이다. (소수점이 여러개일 수는 없다는 점을 확인해야한다.)

if 조건문을 이용해서 마지막 입력값이 숫자이고 소수점이 아니라는 조건을 건다(lastNumeric 과 lastDot 이라는 변수를 이용).

만약 조건이 만족하면 실행해야하는 건 소수점 추가를 하는 코드이다.

 

이렇게 lastNumeric 과 lastDot 처럼 지금 무언가가 활성 상태인지 정지 상태인지를 알려주는 것이

플래그 기능이라고 할 수 있다.


숫자를 계산하는 기능을 만들 때 고려할 점

 

  • 숫자로 끝나지 않는경우나 공백은 연산이 불가능 하다.
  • 음의 정수를 계산해야할 수 있어야 한다
  • 연산자가 두개  이상 와도 계산이 가능해야 한다.( 2+2+2 )

let 문법

fun <T, R> T.let(block: (T) -> R): R

let 함수는 타입 T의 확장 함수이다.

따라서 모든 타입의 객체에 체인 메소드 방식으로 사용할 수 있다.

 

let 함수는 람다식으로 중괄호를 채워서 이용한다.

그리고 let 함수는 스스로의 객체를 인자로 받아서 사용하는데 중괄호 내부에서 그 객체를 it 키워드로 호출이 가능하다.

fun main() {
    val a:String = "m"  // 먼저, let 함수를 사용할 객체를 선언합니다.
    
    a.plus("e").plus("o").plus("ru").let { it.plus("1"); print(it) }

    // 기존 코드
    // a.plus("e").plus("o").plus("ru").plus("1"); print(a.plus("e").plus("o").plus("ru").a)
}

it 키워드가 아니라 인자의 이름을 직접 명명할 수도 있다.

fun main() {
    val a:String = "meoru"
    
    a.let { str -> str.plus("1"); print(str) }
}

특히 세이프콜(Safe Call, "?.")을 이용해서 객체가 null 인 경우를 따로 처리해줄 수 있다.

 

fun main() {
    var str:String? = null

    str?.let {str = "-tech"}?: run{ str = "meoru" }
    print(str)
    str?.let {str = "-tech"}?: run{ str = "meoru" }
    print(str)
}

문자열 자르기 split

split 함수를 이용하면 delimiter를 기준으로 문자열을 자를 수 있다.

예를들어 delimiter가 쉼표라면 문자열을 쉼표를 기준으로 자른다.

split의 리턴값은 List다.

문자열.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String>

위 인수 중 ignoreCase, limit는 생략 가능하며 생략시 기본값이 사용된다. 일반적인 경우는 delimiters만 지정하면 된다.

fun main() {
    var input = "brave new world"
    println(input) // brave new world
    var token = input.split(' '); // delimiter는 공백
    println(token) // brave, new, world
    println(token[0]) // brave
    println(token[1]) // new
    println(token[2]) // world
}

개수를 기준으로 문자열을 자를 땐 chunked 함수를 이용한다.

리턴값도 마찬가지로 list 다. size 에는 자를 개수를 입력한다.

문자열.chunked(size: Int): List<String>
fun main() {
    var input = "brave new world"
    println(input) // brave new world
    var token = input.chunked(2);
    println(token) // brave, new, world
    println(token[0]) // br
    println(token[1]) // av
    println(token[2]) // e
    println(token[3]) // ne
    println(token[4]) // w
    println(token[5]) // wo
    println(token[6]) // rl
    println(token[7]) // d
}


ref:

https://lktprogrammer.tistory.com/132

 

[Android] 안드로이드 - 리니어 레이아웃 (Linear Layout)

안드로이드(Android) 앱을 개발하기 위해서는 반드시 화면이 필요합니다. 그리고 화면에 보이는 구성 요소들은 모두 뷰(View)라고 부릅니다. 우리가 흔히 보는 Button, TextBox, Image 등은 모두 뷰(View)이

lktprogrammer.tistory.com

https://meoru-tech.tistory.com/36

 

💡 [Kotlin/코틀린] let 함수가 뭐죠?

let 함수의 정의 fun T.let(block: (T) -> R): R let 함수는 타입 T의 확장함수입니다. ※ 타입 T란? 따라서 모든 타입의 객체에 Chain Method(점(.)으로 이어나가는) 방식으로 사용할 수 있습니다. 반환 타입도..

meoru-tech.tistory.com

 

728x90
반응형