[새싹] 현대IT&E 240115 기록 - Kotlin

최정윤·2024년 1월 15일
0

새싹

목록 보기
53/67

05. 화면 구성하기 뷰(위젯)

  1. 뷰: UI 구성요소의 기본 클래스이면서 화면을 구성하는 기본 단위이다. 뷰의 종류로는 버튼, 텍스트뷰, 이ㅂ미지뷰 같은 위젯과 컨스트레인트 레이아웃, 리니어 레이아웃과 같은 뷰 그룹이 있다.
  2. 위젯(뷰): 위젯은 화면에 직접적으로 보이고 사용자와 상호작용하는 구성요소이다. 위젯은 뷰 그룹에 속해야 한다. 텍스트뷰, 버튼, 에디트텍스트 등의 위젯을 통해 사용자의 이벤트를 처리하고 정보를 보여준다. 위젯을 편의상 뷰라고 부르다.
  3. 뷰 그룹(레이아웃): 뷰 그룹은 한 개 이상의 뷰 혹은 다른 뷰 그룹을 담고 뷰들을 배치하는 역할을 한다. 뷰 그룹을 레이아웃이라고도 부른다. 뷰 그룹을 레이아웃으로 부르겠다.

5.2 뷰 공통 속성

5.2.1 너비와 높이

activity_patch9.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
        <Button
            android:background="@drawable/ic_launcher_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="안녕하세요"/>
    </LinearLayout>

</ScrollView>

5.2.2 패딩과 마진

activity_padding_and_margin.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#D7FAEA"
        android:text="패딩, 마진 둘 다 없음"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#4B653B"
        android:text="패딩, 마진 둘 다 없음"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="#D7FAEA"
        android:text="마진만 있음"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="#4B653B"
        android:text="마진만 있음"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#D7FAEA"
        android:padding="10dp"
        android:text="패딩만 있음"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="#D7FAEA"
        android:padding="10dp"
        android:text="패딩, 마진 둘 다 있음"
        android:textSize="20sp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="#D7FAEA"
        android:padding="10dp"
        android:text="패딩, 마진 둘 다 있음"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />
</LinearLayout>

5.3 텍스트뷰

5.3.1 텍스트뷰의 기본 속성



sample_textview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="안녕하세요. 조이스입니다."
        android:textColor="#000000"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

5.3.2 strings.xml과 colors.xml 사용하기

values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorMain">#000000</color>
    <color name="colorSub">#25A632</color>
</resources>

values/strings.xml

<resources>
    <string name="app_name">LearningViews</string>
    <string name="greeting">안녕하세요 조이스입니다.</string>
</resources>

sample_textview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/greeting"
        android:textColor="@color/colorMain"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

[추가] 언어별로 values 나누기

activity_value_text.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/greeting"
        android:textColor="@color/colorMain"
        android:textSize="20sp"
        android:textStyle="bold" />
</LinearLayout>

values/strings.xml

<resources>
    <string name="app_name">LearningViews</string>
    <string name="greeting">Hello, My name is Joyce.</string>
</resources>

values-ja/string.xml

<resources>
    <string name="app_name">学習ビュー</string>
    <string name="greeting">こんにちは、ジョイスです。</string>
</resources>

values-ko/string.xml

<resources>
    <string name="app_name">뷰를 배웁니다.</string>
    <string name="greeting">안녕하세요 조이스입니다.</string>
</resources>

5.4 이미지뷰

sample_imageview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/sample_img"
        android:scaleType="center"
        />
</LinearLayout>

activity_matrix.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:id="@+id/imageView"
        android:src="@drawable/katz"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="matrix"/>
</FrameLayout>

MatrixActivity.kt

package com.example.learningviews

import android.graphics.Matrix
import android.graphics.Outline
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.ViewOutlineProvider
import android.view.animation.Animation
import android.view.animation.RotateAnimation
import android.widget.ImageView

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

        // ImageView 참조
        val imageView = findViewById<ImageView>(R.id.imageView)

        imageView.post {
            // 이미지의 중심점을 계산
            val pivotX = imageView.width / 2f
            val pivotY = imageView.height / 2f

            // 이미지 회전을 위한 Matrix 객체 생성
            val matrix = Matrix().apply {
                postRotate(45f, pivotX, pivotY)
            }

            // Matrix 적용
            imageView.imageMatrix = matrix
        }

        // 원형 모양으로 이미지 뷰 설정
        imageView.outlineProvider = object : ViewOutlineProvider() {
            override fun getOutline(view: View, outline: Outline) {
                // 이미지 크기에 맞는 원형 영역 정의
                val size = Math.min(view.width, view.height)
                outline.setOval(0, 0, size, size)
            }
        }
        imageView.clipToOutline = true

        imageView.setOnClickListener {
            // 360도 회전 애니메이션
            val rotateAnimation = RotateAnimation(
                0f, 360f,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f
            ).apply {
                duration = 1000
                repeatCount = 0
            }
            imageView.startAnimation(rotateAnimation)
        }
    }
}

5.6 에디트텍스트

5.6.1 에디트텍스트 만들기

sample_edittext.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Hello World라고 입력해주세요."
        android:padding="10dp"
        android:layout_margin="10dp"
        />
</LinearLayout>

5.6.2 에디트텍스트의 다양한 속성: 비밀번호, 전화번호, 이메일, 날짜

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="비밀번호를 입력해주세요."
        android:inputType="textPassword"
        android:padding="10dp"
        android:layout_margin="10dp"
        />
</LinearLayout>

06. 화면 구성하기 레이아웃(뷰 그룹)

6.1 레이아웃 종류

  1. 리니어 레이아웃: 수직 방향 혹은 수평 방향 차례로 주어진 뷰를 정렬한다.
  2. 상대적 레이아웃: 상대적 레이아웃을 사용하면 뷰들이 다른 뷰들로부터 위치를 지정하거나 자신이 속한 레이앙수을 기준으로 위치를 정한다. 예를 들면 'A 뷰의 오른쪽에 위치', '부모 레이아웃의 정중아에 위치'와 같이 지정할 수 있다.
  3. 컨스트레인트 레이아웃: 뷰 사이에 수평, 수직 방향의 제약을 주어 뷰들을 위치시킨다.
  4. 테이블 레이아웃: 뷰를 행과 열로 구성하여 표의 형태로 표현한다.
  5. 프레임 레이아웃: 뷰들을 액자처럼 쌓아놓는다. 여러 뷰들을 추가하더라도 가장 나중에 추가한 뷰가 가장 위에 위치하게 되는 것이다. 레이아웃 내에 여러 뷰들을 배치시키는데는 적합하지 않고 주로 화면에 표시될 하나의 뷰를 바꿔가며 표시하는데 적합하다.

6.2 리니어 레이아웃: LinearLayout

6.2.1 리니어 레이아웃의 기본 속성

linear_layout_1.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button3" />

</LinearLayout>

6.2.2 독립적으로 위치를 지정하는 layout_gravity 속성 알아보기

[ToDo] 레이아웃의 방향이 vertical일 때 배치

linear_layout_2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:text="button1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="button2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:text="button3" />

</LinearLayout>

[ToDo] 레이아웃의 방향이 vertical일 때 배치

linear_layout_3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:text="button1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="button2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="button3" />

</LinearLayout>

6.2.3 비중을 지정하는 layout_weight 속성 알아보기

linear_layout_4.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="4">

    <Button
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="1" />

    <Button
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content"
        android:text="2" />

    <Button
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="1" />

</LinearLayout>

6.3 상대적 레이아웃: RelativeLayout

6.3.1 상대적 레이아웃의 기본 속성

[ToDo] 부모 레이아웃을 기준으로 배치하기

relative_layout_1.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:text="parent/nstart" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:text="parent/nend" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="parent bottom" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:text="parent bottom\n + parent end" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="parent/ncenter" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="center/nhorizontal" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:text="center/nvertical" />

</RelativeLayout>

[ToDo] 자식 뷰끼리 기준으로 배치하기

relative_layout_2.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/standard_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:text="기준 1" />

    <Button
        android:id="@+id/standard_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="기준 2" />

    <Button
        android:id="@+id/standard_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:text="기준 3" />

</RelativeLayout>

6.4 컨스트레인트 레이아웃: ConstraintLayout

6.4.1 컨스트레인트 레이아웃 기본 속성

constraint_layout_1.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button
        android:id="@+id/button_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="32dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="100dp"
        android:text="Button 1"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@id/button_1"
        app:layout_constraintBotton_toBottomOf="@id/button_1"
        app:layout_constraintTop_toTopOf="@id/button_1"
        android:layout_marginStart="32dp"
        android:text="버튼을 클릭해주세요!"
        />
        
</androidx.constraintlayout.widget.ConstraintLayout>

6.4.2 컨스트레인트 레이아웃에서 마진을 줄 때 주의점

constraint_layout_2.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Button
        android:id="@+id/button_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="100dp"
        android:text="Button 1"/>
    
    <Button
        android:id="@+id/button_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@id/button_1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/button_1"
        android:text="Button 2" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

constraint_layout_3.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ff7e67"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@id/vertical"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/horizontal"
        android:text="LEFT"
        android:gravity="center"
        android:textSize="30dp" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#006a71"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/vertical"
        app:layout_constraintTop_toTopOf="@+id/horizontal"
        android:text="RIGHT"
        android:gravity="center"
        android:textSize="30dp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#A0CAC7"
        app:layout_constraintBottom_toBottomOf="@id/horizontal"
        app:layout_constraintTop_toTopOf="parent"
        android:text="TOP"
        android:gravity="center"
        android:textSize="30dp" />
    
    <androidx.constraintlayout.widget.Guideline
        android:id="@id/horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.3" />
    
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@id/vertical"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.4" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

07. 스톱워치 스레드

7.3 레이아웃 구성하기

7.3.2 colors.xml과 strings.xml 설정

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>

    <color name="blue">#603CFF</color>
    <color name="red">#FF6767</color>
    <color name="yellow">#E1BF5A</color>
</resources>

strings.xml

<resources>
    <string name="app_name">StopWatch</string>
    <string name="start">시작</string>
    <string name="pause">일시정지</string>
    <string name="refresh">초기화</string>
</resources>

7.3.4 텍스트뷰 추가: 체인 사용해보기

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
    
    <TextView
        android:id="@+id/tv_minute"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00"
        android:textSize="45sp" 
        />
    
    <TextView
        android:id="@+id/tv_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":00"
        android:textSize="45sp"
        />
    
    <TextView
        android:id="@+id/tv_millisecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=".00"
        android:textSize="30sp"
        />
    
    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginBottom="80dp"
        android:padding="20dp"
        android:backgroundTint="@color/blue"
        android:text="@string/start"
        android:textColor="@color/white"
        android:textSize="16sp"
        android:textStyle="bold"
        />

    <Button
        android:id="@+id/btn_refresh"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/btn_start"

        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_margin="50dp"
        android:padding="20dp"
        android:backgroundTint="@color/yellow"
        android:text="@string/refresh"
        android:textColor="@color/white"
        android:textSize="16sp"
        android:textStyle="bold"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

7.4 버튼에 이벤트 연결하기

MainActivity.kt

package com.example.stopwatch

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView

class MainActivity : AppCompatActivity(), View.OnClickListener {

    var isRunning = false

    private lateinit var btn_start: Button
    private lateinit var btn_refresh: Button
    private lateinit var tv_millisecond: TextView
    private lateinit var tv_second: TextView
    private lateinit var tv_minute: TextView

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

        btn_start = findViewById(R.id.btn_start)
        btn_refresh = findViewById(R.id.btn_refresh)
        tv_millisecond = findViewById(R.id.tv_millisecond)
        tv_second = findViewById(R.id.tv_second)
        tv_minute = findViewById(R.id.tv_minute)
        
        btn_start = findViewById(R.id.btn_start)
        btn_refresh = findViewById(R.id.btn_refresh)
        tv_millisecond = findViewById(R.id.tv_millisecond)
        tv_second = findViewById(R.id.tv_second)
        tv_minute = findViewById(R.id.tv_minute)
        
        btn_start.setOnClickListener(this)
        btn_refresh.setOnClickListener(this)
    }
    
    override fun onClick(v: View?) {
        when(v?.id) {
            R.id.btn_start -> {
                if(isRunning) {
                    pause()
                } else {
                    start()
                }
            }
            R.id.btn_refresh -> {
                refresh()
            }
        }
    }
    
    private fun start() {
        
    }
    
    private fun pause() {
        
    }
    
    private fun refresh() {
        
    }
}

7.5 스톱워치 시작 기능 구현하기

MainActivity.kt

package com.example.stopwatch

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView
import java.util.Timer

class MainActivity : AppCompatActivity(), View.OnClickListener {

    var isRunning = false
    var timer : Timer? = null
    var time = 0

    private lateinit var btn_start: Button
    private lateinit var btn_refresh: Button
    private lateinit var tv_millisecond: TextView
    private lateinit var tv_second: TextView
    private lateinit var tv_minute: TextView

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

        btn_start = findViewById(R.id.btn_start)
        btn_refresh = findViewById(R.id.btn_refresh)
        tv_millisecond = findViewById(R.id.tv_millisecond)
        tv_second = findViewById(R.id.tv_second)
        tv_minute = findViewById(R.id.tv_minute)

        btn_start = findViewById(R.id.btn_start)
        btn_refresh = findViewById(R.id.btn_refresh)
        tv_millisecond = findViewById(R.id.tv_millisecond)
        tv_second = findViewById(R.id.tv_second)
        tv_minute = findViewById(R.id.tv_minute)

        btn_start.setOnClickListener(this)
        btn_refresh.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        when(v?.id) {
            R.id.btn_start -> {
                if(isRunning) {
                    pause()
                } else {
                    start()
                }
            }
            R.id.btn_refresh -> {
                refresh()
            }
        }
    }

    private fun start() {
        btn_start.text = "일시정지"
        btn_start.setBackgroundColor(getColor(R.color.red))
        isRunning = true
        
        timer = timer(period = 10) {
            time++
            
            val milli_second = time % 100
            val second = (time % 6000) / 100
            val minute = time / 6000
            
            runOnUiThread {
                if(isRunning) {
                    tv_millisecond.text = if (milli_second < 10)
                        ".0${milli_second}" else ".${milli_second}"
                    tv_second.text = if(second < 10) ":0${second}" else ":${second}"
                    tv_minute.text = "${minute}"
                }
            };
            tv_millisecond.text = 
                if (milli_second < 10) ".0${milli_second}" else ".${milli_second}"
            tv_second.text = if(second < 10) ":0${second}" else ":${second}"
            tv_minute.text = "${minute}"
        }
    }

    private fun pause() {
        
    }

    private fun refresh() {
        
    }
}

7.6 일시정지 기능 구현하기

MainActivity.kt 일부

private fun pause() {
        btn_start.text = "시작"
        btn_start.setBackgroundColor(getColor(R.color.blue))
        
        isRunning = false
        timer?.cancel()
    }

7.7 초기화 기능 구현하기

MainActivity.kt 일부

private fun refresh() {
        timer?.cancel()

        btn_start.text = "시작"
        btn_start.setBackgroundColor(getColor(R.color.blue))
        isRunning = false

        time = 0
        tv_millisecond.text = ".00"
        tv_second.text = ":00"
        tv_minute.text = "00"
    }

최종코드

MainActivity.kt

package com.example.stopwatch

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.View
import android.widget.Button
import android.widget.TextView
import java.util.Timer
import kotlin.concurrent.timer

class MainActivity : AppCompatActivity(), View.OnClickListener {

    var isRunning = false
    var timer: Timer? = null // O timer 변수 추가
    var time = 0

    private lateinit var btn_start: Button
    private lateinit var btn_refresh: Button
    private lateinit var tv_minute: TextView
    private lateinit var tv_second: TextView
    private lateinit var tv_millisecond: TextView

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

        btn_start = findViewById(R.id.btn_start)
        btn_refresh = findViewById(R.id.btn_refresh)
        tv_minute = findViewById(R.id.tv_minute)
        tv_second = findViewById(R.id.tv_second)
        tv_millisecond = findViewById(R.id.tv_millisecond)

        btn_start.setOnClickListener(this)
        btn_refresh.setOnClickListener(this)
    }

    override fun onClick(view: View?) {
        when (view?.id) {
            R.id.btn_start -> {
                if (isRunning) {
                    pause()
                } else {
                    start()
                }
            }

            R.id.btn_refresh -> {
                refresh()
            }
        }
    }

    private fun start() {
        btn_start.text = resources.getText(R.string.pause)
        btn_start.setBackgroundColor(getColor(R.color.red))

        isRunning = true // 실행 상태 변경


        // 스톱워치를 시작하는 로직
        timer = timer(period = 10) {
            time++ // 10 밀리초 단위 타이머

            /*
            e. 01:15:15 ==> 75.15초
            ms      --> 7515 % 100      = 15 ms
            second  --> 7515 / 100 % 60 = 15 second
            minutes --> 7515 / 100 / 60 =  1 minutes
             */

            // 시간 계산
            val milli_second = time % 100
            val second = time / 100 % 60
            val minute = time / 100 / 60

            runOnUiThread {
                if (isRunning) {
                    tv_millisecond.text = ",%02d".format(milli_second)
                    tv_second.text = ":%02d".format(second)
                    tv_minute.text = "%02d".format(minute)
                }
            }
        }
    }

    private fun refresh() {
        timer?.cancel()

        btn_start.text = resources.getText(R.string.start)
        btn_start.setBackgroundColor(getColor(R.color.blue))
        isRunning = false // 멈춤 상태로 변경

        // 타이머 초기화
        time = 0
        tv_millisecond.text = ",00"
        tv_second.text = ":00"
        tv_minute.text = "00"
    }

    private fun pause() {
        btn_start.text = resources.getText(R.string.start)
        btn_start.setBackgroundColor(getColor(R.color.blue))
        isRunning = false
        timer?.cancel()
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">

    <TextView
        android:id="@+id/tv_minute"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:text="00"
        android:textSize="45sp"
        app:layout_constraintBaseline_toBaselineOf="@+id/tv_second"
        app:layout_constraintEnd_toStartOf="@+id/tv_second"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/tv_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="219dp"
        android:text=":00"
        android:textSize="45sp"
        app:layout_constraintEnd_toStartOf="@+id/tv_millisecond"
        app:layout_constraintStart_toEndOf="@+id/tv_minute"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_millisecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="9dp"
        android:text=".00"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="@+id/tv_second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/tv_second" />

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="80dp"
        android:backgroundTint="@color/blue"
        android:padding="20dp"
        android:text="@string/start"
        android:textColor="@color/white"
        android:textSize="16sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btn_refresh"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="50dp"

        android:backgroundTint="@color/yellow"
        android:padding="20dp"
        android:text="@string/refresh"
        android:textColor="@color/white"
        android:textSize="16sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/btn_start"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

profile
개발 기록장

0개의 댓글