세현's 개발로그

XML 사용법과 UI 생성법 배우기 본문

Kotlin

XML 사용법과 UI 생성법 배우기

SarahPark 2022. 10. 31. 13:16

#1 선형 레이아웃을 이용해서 계산기 UI 만들기 파트 1

 

1. LinearLayout(세로 또는 가로의 단일 방향으로 모든 하위 요소를 정렬하는 뷰 그룹)을 사용한다.

2. 선형 레이아웃 안에 텍스트 뷰를 만들어준다. 그리고 텍스트 뷰의 너비는 상위 요소와 맞추고 높이는 250dp로 정한다. 글자 색을 옅은 회색으로 해주기 위해 colors.xml 창에서 새 색상 코드를 만들어주고 Hex 코드를 붙여 옅은 회색의 코드를 만들어준다.

3. padding 기능으로 글자와 텍스트 뷰 사이에 공간이 생기도록 코드를 입력해준다. 그 다음으로 textSize로 글자 크기를 48sp로 하고, text에 값을 할당해준다.

<TextView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:background="@color/light_grey"
        android:padding="10dp"
        android:textSize="48sp"
        android:text="124123"
        />

현재까지의 구현 모습

 

4. 글자를 텍스트 뷰 내부의 오른쪽 밑에 표시되도록 바꿔주었다. gravity 속성에 'right'와, | 기호를 적고 'bottom'을 적어준다. 'right'가 가독성은 높지만 IDE에서 'end'를 추천하기 때문에 'end'로 바꿔준다. 

5. 문자열을 text 값에 바로 넣어주면 하드코딩이 되기 때문에 문자열을 strings.xml 같은 파일에 따로 담아주어야 한다. 

//strings.xml
<resources>
    <string name="app_name">MyCalculator</string>
    <string name="calc_text">1234567890</string>
</resources>

 

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

 

6. 버튼을 만들어주기 위해 선형 레이아웃 안에 새로운 선형 레이아웃을 만들어준다. 'wrap_content'로 아이템의 높이를 내용물을 기준으로 설정해준다.

7. 선형 레이아웃이 여러 개 존재한다면 각 요소의 방향을 정의해야 한다. 방향을 orientation에 할당해준다. 'vertical'은 수직 방향, 'horizontal'은 수평 방향을 의미한다.

8. 선형 레이아웃 내부에 버튼을 생성해주는데, 너비는 0dp로 설정하는데 이는 너비가 없는 게 아니다. 높이는 'match_parent'로 상위 요소의 높이에 맞춰 생성되는데, 'wrap_content' 덕분에 자동으로 맞춰진다.

9. 가중치를 "1"로 할당해준다. 그리고 text에 값도 7로 넣어준다.

10. 모든 버튼은 ID가 있기 때문에 ID값도 할당해준다.

11. 각각의 버튼을 복사 붙여넣기 하여 똑같이 만들어준다.

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnSeven"
            android:layout_widh="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="7"/>
        <Button
            android:id="@+id/Eight"
            android:layout_widh="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="8"/>
        <Button
            android:id="@+id/btnNine"
            android:layout_widh="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="9"/>
    </LinearLayout>

현재까지의 구현 모습

 

12. 버튼끼리의 간격을 주기 위해 'layout_margin'으로 2dp정도 여백을 준다.

13. 버튼에 기능을 부여하기 위해 onClick 속성을 추가해준다.

14. 메인문에 'function' 메소드로 'onDigit' 뒤에 'view'를 추가해준다. 'view'가 버튼을 눌렀을 때 버튼을 대신해준다. 그러고 나서 버튼이 작동하는지 확인할 수 있는 텍스트를 넣어주었다.

//MainActivity.kt
fun onDigit(view: View){
        Toast.makeText(this,"Button clicked",Toast.LENGTH_LONG).show()
    }
<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="/"/>

현재까지의 구현 모습

#2 선형 레이아웃을 이용해서 계산기 UI 만들기 파트 2

 

15. 만들어놓은 선형 레이아웃을 여러 개 복사해 줄 건데, 그러기 위해서 선형 레이아웃에 가중치를 할당해준다.

16. 원하는 형식에 맞게 버튼들의 text 내용과 id 내용을 수정해준다.

17. 버튼 색들을 원하는 색으로 바꿔주기 위해 색상이 정의된 themes 창으로 가면 'colorPrimary'가 버튼의 색이라는 걸 확인할 수 있다. 'color'를 사용해 새로운 색을 만들어준다.

현재까지의 구현 모습

 

#3 onClick으로 CLR 기능 구현하기

 

18. 이전에 onDigit 함수로 토스트에 문구를 표시했었다. 문구 대신 텍스트 뷰의 입력창에 뭔가를 적도록 기능을 구현해보겠다. 텍스트 뷰의 ID부터 'tvInput'으로 만들어준다. onDigit 함수에서 ID를 사용해 찾는다.

19. 메인에서 'private' 접근형식 변수를 만든다. nullable한 'TextView'타입을 만들기 위해 null로 값을 설정하면 onCreate 메소드에서 사용할 수 있다.

20. findViewById로 ID가 'tvInput'인 것을 찾는다. 이제 onDigit에서 tvInput을 사용할 수 있다. onDigit에서 사용할 때 주의할 점은 물음표를 붙여줘야 null인 경우 코드가 실행되지 않고, null이 아니면 실행된다.

21. 숫자는 누르던 버튼에서 가져올 수 있다. onDigit이 호출될 때는 뷰 부분이 메소드를 불러온다. 그래서 onClick으로 버튼의 ID, 텍스트 등을 포함한 모든 속성의 정보가 전부 onDigit 메소드로 이동한다.

class MainActivity : AppCompatActivity() {

    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)
    }
}

22. CLR 버튼의 기능을 구현하기 위해 새 function 'onClear'를 추가해준다. 이 메소드는 텍스트를 빈 문자열로 설정해준다.

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

#4 onDecimalPoint 기능 추가하기

 

23. 소수점 기능을 추가하면 float 계산을 할 수 있다. 'btnDot'이라는 버튼을 하나 추가해준다. 

 <Button
            android:layout_margin="2dp"
            android:id="@+id/btnDot"
            android:layout_witdh="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" //가중치를 1로 바꿔줌
            android:onClick="onDigit"
            android:text="."/>

현재까지의 구현 모습

 

24. 이제 소수점 버튼을 눌렀을 때 필요한 특정 메소드를 만들어준다. 이름은 'onDecimalPoint'라고 해준다. 중요한 점은 마지막 정보 값이 점이 아닐 때만 실행되게 만든다. 그러려면 두 개의 변수가 더 필요하다. 각각 마지막에 숫자를 입력했는지, 소수점을 입력한 건지를 알려준다. Boolean 타입인 'lastNumeric'을 true, 'lastDot'을 false라 설정한다. 

25. 이미 소수점을 입력한 경우 다시 소수점이 입력되지 않게 하기 위해 조건문을 사용한다.

//변수 선언
var lastNumeric:Boolean=true
    var lastDot:Boolean=false
    
//메소드
 fun onDecimalPoint(view: View){
        if(lastNumeric&&!lastDot){
            tvInput?.append(".")
            lastNumeric=false
            lastDot=true
        }

#5 포함과 문자열의 StartWith로 OnOperator 기능 추가하기

 

26. 연산자가 추가됐는지 확인할 메소드가 새로 필요하다. 'isOperatorAdded'라는 이름으로 정의해주겠다. 이 메소드는 Boolean을 return 해준다. 이는 마이너스 기호가 앞에 오는 경우 빼고 숫자 앞에 기호들이 포함 됐는지 알려준다.

private fun isOperatorAdded(value:String):Boolean{
        return if(value.startsWith("-")){
            false
        }else{
            value.contains("/")
                    ||value.contains("*")
                    ||value.contains("+")
                    ||value.contains("-")
        }

27. 이 메소드를 이용하기 위해 onOperator 메소드를 사용해 연산자를 사용한 경우에 불러온다. if문으로 마지막 입력값이 숫자인지 확인하고 'isOperatorAdded'가 true인지 확인한다.

    fun onOperator(view: View){
        tvInput?.text?.let{
            if(lastNumeric&&!isOperatorAdded(it.toString())){
                tvInput?.append((view as Button).text)
                lastNumeric=false
                lastDot=false
            }
        }
    }

#6 뺄셈 추가하기 - 나눗셈과 문자열의 문자열 자르기 사용

 

28. 등호 버튼을 눌렀을 때 마지막 입력값이 숫자인지 알아야 한다. 그래야 '99-'처럼 계산이 불가능한 식을 계산하는 것을 방지할 수 있다. 따라서 등호 버튼을 눌렀을 때 실행되는 onEqual 메소드를 만든다.

29. 0으로 나누거나 산술적으로 계산이 불가능할 때를 예외로 인식해서 에러를 잡아주기 위해 try-catch 구문을 만들어준다.

30. 문자열을 나누기 위해 split을 사용해준다. '99-1'이라는 문자열이 있다고 생각했을 때 첫 번째 입력값이 '99'고 두 번째 입력값이 '1'이 되도록 해주는 것이다.

31. 음수가 앞에 나오는 것을 처리해주기 위해 prefix 수식 표기법을 사용해준다. 

    fun onEqual(view:View){
        if(lastNumeric){
            var tvValue=tvInput?.text.toString()
            var prefix=""
            try{
                if(tvValue.startsWith("-")){
                    tvValue=tvValue.substring(1)
                }
                if(tvValue.contains("")) {

                    val splitValue = tvValue.split("-")
                    
                    var one = splitValue[0] //99
                    var two = splitValue[1] //1
                    if (prefix.isNotEmpty()) {
                        one = prefix + one
                    }
                }
                
                tvInput?.text=(one.toDouble()-two.toDouble()).toString()
            }catch (e:ArithmeticException){
                e.printStackTrace()
            }
        }
    }

#7 Missing Operations 추가하고 앱 완성하기

32. 위 과정에서 빼기 연산을 완성했으니 코드를 복사 붙여넣기 해서 나머지 연산들도 같은 방식으로 완성한다.

33. '66-33'을 계산해주었을 때 33.0이 결과로 나온다. 뒤에 붙은 .0을 제거해주기 위해 private 접근 형식으로 removeZeroAfterDot이라는 기능을 만들어준다. substring 기능을 이용해 범위를 index 0부터 'result.ength-2'까지 지정해준다.

34. 모든 텍스트 속성 뒤에 removeAfterDot을 추가하고 계산 코드를 실행해준다.

private fun removeZeroAfterDot(result:String) : String{
        var value=result
        if(result.contains(".0"))
            value=result.substring(0,result.length-2)
        
        return value
    }
//모든 텍스트 속성 뒤에 removeZeroAfterDot을 추가해줌
tvInput?.text=removeZeroAfterDot((one.toDouble()-two.toDouble()).toString())

 

완성!!

'Kotlin' 카테고리의 다른 글

코틀린-퀴즈 앱  (0) 2022.11.03
Kotlin 개발 완전 정복(2)  (0) 2022.10.06
Kotlin 개발 완전 정복(1)  (0) 2022.09.27
Comments