티스토리 뷰

 

-새로은 모듈에서 작업 : file - New Module : phone&tablet / lab06 / empty activity

 

터치 이벤트, 클릭 이벤트 차이

-터치 : 액티비티 단위. up/down/touch. 드래그(drag)할 수 있음

-Keypad 이벤트 : 하드웨어. 자판기 키보드. Keyboard 이벤트 : 하드웨어적인 것. 전원버튼, 볼륨조절버튼, 네이게이션바

└프로그램적으로 올라오는 키패드는 Keyboard 이벤트가 아님(텍스트 에디터)

 

1. 터치 이벤트 - onTouchEvent()

(1) 터치 이벤트 종류

-Java의 case문과 동일 : when

-log.d()는 로그캣에 출력

-rawX, rawY는 화면 좌표

 

(1-1) MainActivity.kt

package com.example.lab06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent

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

    override fun onTouchEvent(event: MotionEvent?): Boolean { //Null 허용, 리턴형 boolean
        when(event?.action){ //위에서 event Null허용해줬기  때문에 같이 맞춰줘야함.
            MotionEvent.ACTION_DOWN -> {
                Log.d("Android", "Touch down Event")
            }
            MotionEvent.ACTION_UP -> {
                Log.d("Android", "Touch up Event")
            }
        }
        return super.onTouchEvent(event)
    }
}

>> 실행(pLay) : MainActivity 우클릭 실행

실행된 화면을 터치(클릭)하면 아래의 내용이 logcat에 찍힘.

2022-04-18 12:32:25.655 6831-6831/com.example.lab06 D/Android: Touch down Event
2022-04-18 12:32:25.758 6831-6831/com.example.lab06 D/Android: Touch up Event

 

(1-2) 뷰바인딩(viewBinding) 설정

-build.gradle

    viewBinding{
        enabled=true
    }

>> 저장 후 싱크(sync) 해줘야 적용됨.

 

-MainActivity.kt

package com.example.lab06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import com.example.lab06.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

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

        val binder = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binder.root)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean { //Null 허용, 리턴형 boolean
        when(event?.action){ //위에서 event Null허용해줬기  때문에 같이 맞춰줘야함.
            MotionEvent.ACTION_DOWN -> {
                Log.d("Android", "Touch down Event")
            }
            MotionEvent.ACTION_UP -> {
                Log.d("Android", "Touch up Event")
            }
            MotionEvent.ACTION_MOVE -> {
				Log.d("Android", "Touch Move Event x : ${event.x}, y:${event.y}")
            }
        }
        return super.onTouchEvent(event)
    }
}

└드래그했을 때, 좌표가 로그캣에 뜸.

 

(1-3) (1-1)와 똑같은 효과

-res/layout/activity_main.xml

textView의 아이디 tvResult

package com.example.lab06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import com.example.lab06.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding //★
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)

        val binder = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binder.root)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean { //Null 허용, 리턴형 boolean
        when(event?.action){ //위에서 event Null허용해줬기  때문에 같이 맞춰줘야함.
            MotionEvent.ACTION_DOWN -> {
                Log.d("Android", "Touch down Event")
            }
            MotionEvent.ACTION_UP -> {
                Log.d("Android", "Touch up Event")
            }
            MotionEvent.ACTION_MOVE -> {
                binding.tvResult.text="Touch Move Event x : ${event.x}, y:${event.y}" //★
                //Log.d("Android", "Touch Move Event x : ${event.x}, y:${event.y}")
            }
        }
        return super.onTouchEvent(event)
    }
}

└raw x, raw y : 화면 좌표

 

(2) 키(Key) 이벤트

-사용자가 폰의 키를 누르는 순간 발생. 텍스트에디터는 키(Key) 아님.

-키 이벤트에 해당하는 뒤로 가기 버튼(KEYCODE_BACK), 볼륨 버튼(KEYCODE_VOLUME_UP/DOWN), 전원 버튼 등등

(2-1) 콜백함수

onKeyDown onKeyUp onKeyLongPress
키를 누른 순간 키를 떼는 순간 키를 오래 누르는 순간

볼륨 업/ 볼륨 다운 / 뒤로가기(Back) / 홈(Home) / 오버뷰(Overview)

 

>> New Project : Application06

 

-MainActivity.kt

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent

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

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        when(keyCode){
            KeyEvent.KEYCODE_BACK -> Log.d("wsy", "Back Button을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_UP -> Log.d("wsy", "Volume_up 버튼을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_DOWN -> Log.d("wsy", "Volume_down 버튼을 눌렀습니다.")
        }
        return super.onKeyDown(keyCode, event)
    }
}

 

-Log.d에 wsy 태그 넣은 것만 로그캣에서 출력하겠다는 뜻.

 

-MainActivity.kt

뒤로 가기 버튼(Back)만 따로 설정하려고 할 때,

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent

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

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        when(keyCode){
            KeyEvent.KEYCODE_BACK -> Log.d("wsy", "Back Button을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_UP -> Log.d("wsy", "Volume_up 버튼을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_DOWN -> Log.d("wsy", "Volume_down 버튼을 눌렀습니다.")
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onBackPressed() {
        Log.d("wsy", "Back Button Down")
        super.onBackPressed()
    }
}

 

 

(3) 뷰 이벤트 - 이벤트 소스 / 이벤트 핸들러

-이벤트 소스 : 이벤트가 발생한 객체

-이벤트 핸들러 : 이벤트 발생 시 실행할 로직이 구현된 객체. 이벤트 처리.

-리스터 : 이벤트 소스와 이벤트 핸들러를 연결해주는 함수 ex) setOnClickListener

 리스너 연결을 어떤 형식으로 하는가??

 

(3-1) 리스너 연결 방식 1 : 익명 리스너

인터페이스 구현하는 클래스 만들지 않고, 인터페이스를 통해 클래스 생성 및 객체 생성까지 대체

간단하게 쓰기에는 편함. 버튼 1, 2개 정도?

//      이벤트소스.리스너(이벤트 핸들러 등록)(이벤트 핸들러:
binding.button.setOnClickListener(Object : View.OnClickListener {
            binding.textView.setText("Button 1 클릭!")
        })

-build.gradle : viewBinding

    viewBinding{
        enabled = true
    }

>> sync(코끼리 아이콘) 해줘야 적용 됨.

 

-activity_main.xml

-버튼 클릭시 해당하는 버튼이 클리되었다는 문구 출력

<?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">


    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 1" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 2" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 3" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" />
</LinearLayout>

-mainactivity.kt

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import com.example.application06.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    //binding
    lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        //binding
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //익명 리스너 : 구현과 동시에 객체 생성
        binding.button.setOnClickListener(View.OnClickListener {
            binding.textView.setText("Button 1 클릭!")
        })
        binding.button2.setOnClickListener(View.OnClickListener {
            binding.textView.setText("Button 2 클릭!")
        })
        binding.button3.setOnClickListener(View.OnClickListener {
            binding.textView.setText("Button 3 클릭!")
        })
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        when(keyCode){
            KeyEvent.KEYCODE_BACK -> Log.d("wsy", "Back Button을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_UP -> Log.d("wsy", "Volume_up 버튼을 눌렀습니다.")
            KeyEvent.KEYCODE_VOLUME_DOWN -> Log.d("wsy", "Volume_down 버튼을 눌렀습니다.")
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onBackPressed() {
        Log.d("wsy", "Back Button Down")
        super.onBackPressed()
    }
}

 

>> 실행(play)

버튼 눌렀을 때, 해당하는 버튼에 따라 text 변경됨

 


<체크박스>

-activity_main.xml

체크박스 입력(디자인에서 드래그)

<?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">
...
    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="사과" />

    <CheckBox
        android:id="@+id/checkBox2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="배" />
</LinearLayout>

>> 실행 : 사과 체크했을 때, 안 했을 때

 

 

-MainActivity.kt

사과, 배 체크했을때, 안 했을 때 이벤트 설정

      //체크박스
        //CompoundButton 자동완성시켰을 때, 2번째 것!!
        binding.checkBox1.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
            if(b){ //그냥도 true
                binding.textView.setText(binding.checkBox1.text) //바인딩된 체크박스1의 텍스트를 -하라?
            }else {
                binding.textView.setText("None Checked")
            }
        })
        binding.checkBox2.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
            if(b){ //그냥도 true
                binding.textView.setText(binding.checkBox2.text) //바인딩된 체크박스1의 텍스트를 -하라?
            }
            else {
                binding.textView.setText("None Checked")
            }
        })

 

-똑같은 효과를 replace로

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.CompoundButton
import com.example.application06.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    //binding
    lateinit var binding: ActivityMainBinding
    //
    var str1 = ""
...
        //체크박스
        //CompoundButton 자동완성시켰을 때, 2번째 것!!
        binding.checkBox1.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
            if(b){ //그냥도 true
                str1 += binding.checkBox1.text
            }else {
                str1=str1.replace(binding.checkBox1.text.toString(), "")
            }
            binding.textView.setText(str1)
        })
        binding.checkBox2.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
            if(b){ //그냥도 true
                str1 += binding.checkBox2.text
            }else {
                str1=str1.replace(binding.checkBox2.text.toString(), "")
            }
            binding.textView.setText(str1)
        })

    }

...
}

└체크(선택)했을 때, 텍스트뷰(textView)에 넣어주고 아닐 때 공백

 

→ 익명함수 사용할 때, 하나하나 다 만들어줘야 함. 귀찮음.

 

(3-2) 리스너 연결 방식 2 : 액티비티에 이벤트 리스터 인터페이스 구현

-View.OnClickListener를 상속 및 구현 → override fun onCreate() 구현

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.CompoundButton
import com.example.application06.databinding.ActivityMainBinding

//(3-2) 액티비티에 이벤트 리스너 인터페이스 구현. 이벤트 핸들러 직접 구현 ↓
class MainActivity : AppCompatActivity(), View.OnClickListener {
    //binding
    lateinit var binding: ActivityMainBinding
    //
    var str1 = ""
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        //binding
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        //(3-2)
        binding.button.setOnClickListener(this) //this - Mainactivity
        binding.button2.setOnClickListener(this)
        binding.button3.setOnClickListener(this)
    }

//  액티비티에 이벤트 리스너 인터페이스 구현
//(3-2) 버튼 눌렀을 때 설정
    override fun onClick(p0: View?) { //어떤 뷰를 클릭했는가?
        when(p0){  //id에 따라 -> 아래와 같이 처리하시오.
            binding.button -> binding.textView.text="버튼1 클릭!"
            binding.button2 -> binding.textView.text="버튼2 클릭!"
            binding.button3 -> binding.textView.text="버튼3 클릭!"
        }
    }
}

(+) 체크박스 구현

package com.example.application06

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.CompoundButton
import com.example.application06.databinding.ActivityMainBinding

//(3-2) 액티비티에 이벤트 리스너 인터페이스 구현. 이벤트 핸들러 직접 구현
class MainActivity : AppCompatActivity(), View.OnClickListener, CompoundButton.OnCheckedChangeListener {
    //binding
    lateinit var binding: ActivityMainBinding
    //
    var str1 = ""
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        //binding
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //(3-2-checkBox)
        binding.checkBox1.setOnCheckedChangeListener(this)
        binding.checkBox2.setOnCheckedChangeListener(this)

        //체크박스
        //CompoundButton 자동완성시켰을 때, 2번째 것!!
        //익명 리스너 : 구현과 동시에 객체 생성
//        binding.checkBox1.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
//            if(b){ //그냥도 true
//                str1 += binding.checkBox1.text
//            }else {
//                str1=str1.replace(binding.checkBox1.text.toString(), "")
//            }
//            binding.textView.setText(str1)
//        })
//        binding.checkBox2.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { compoundButton, b ->
//            if(b){ //그냥도 true
//                str1 += binding.checkBox2.text
//            }else {
//                str1=str1.replace(binding.checkBox2.text.toString(), "")
//            }
//            binding.textView.setText(str1)
//        })

    }

    override fun onCheckedChanged(p0: CompoundButton?, p1: Boolean) {
        when(p0){
            binding.checkBox1 -> {
                if (p1){
                    str1 += binding.checkBox1.text
                }else{
                    str1 = str1.replace(binding.checkBox1.text.toString(), "")
                }
            }
            binding.checkBox2 -> {
                if (p1){
                    str1 += binding.checkBox2.text
                }else{
                    str1 = str1.replace(binding.checkBox2.text.toString(), "")
                }
            }
        }
        binding.textView.setText(str1)
    }
}

 

(3-3) 리스너 연결 방식 3 : 이벤트 리스너 클래스 작성_default 방법

-이걸 간단하게 하기 위해 (2)번 방법이나 (1)으로 사용.

-MainActivity 밖에 만들 수도 안에 만들 수도 있음. 바깥에보다 안에 클래스 만드는게 좋음. 뷰 바인딩을 MainActivity에 했기 때문에.

바깥에다가 클래스를 만들면 뷰바인딩을 별도로 보내줘야 함.

새 패키지 / 새 액티비티 생성

-activity_test1.xml

<?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"
    tools:context=".test1.Test1Activity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/button6"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button7"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TextView" />

    </LinearLayout>
</LinearLayout>

 

-MainActivity.kt

++++++++++++++++++++++++++++

package로 만들면 binding이 잘 안 됨....ㅠㅠ

[ New Module ] 로 하면 됨. - lab6Check

+++++++++++++++++++++++++++CheckBox 실습++++++++++++++++++++++

build.gradle(Module lab6Check)

android {
    compileSdk 32

...
    viewBinding{
        enabled=true
    }
}

-activity_test2.xml

<?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"
    tools:context=".Test2Activity"
    android:orientation="vertical">

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="복숭아" />

    <CheckBox
        android:id="@+id/checkBox2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="블루베리" />

    <CheckBox
        android:id="@+id/checkBox3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="딸기" />
</LinearLayout>

-Test2Activity.kt

package com.example.lab6check

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.CompoundButton
import com.example.lab6check.databinding.ActivityTest2Binding

var data = 0
class Test2Activity : AppCompatActivity() {
    lateinit var binding: ActivityTest2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_test2)
        binding = ActivityTest2Binding.inflate(layoutInflater) //자동완성2
        setContentView(binding.root)
        binding.checkBox.setOnCheckedChangeListener(MyCheckedBoxEventHandler(binding))
        binding.checkBox2.setOnCheckedChangeListener(MyCheckedBoxEventHandler(binding))
        binding.checkBox3.setOnCheckedChangeListener(MyCheckedBoxEventHandler(binding))
    }
}
class MyCheckedBoxEventHandler(binding: ActivityTest2Binding):CompoundButton.OnCheckedChangeListener{
    lateinit var binding: ActivityTest2Binding
    init {
        this.binding = binding
    }

    override fun onCheckedChanged(p0: CompoundButton?, p1: Boolean) {
//        TODO("Not yet implemented")
        when(p0){
            binding.checkBox -> {
                if(p1){
                    data += 10000
                }else{
                    data -= 10000
                }
            }
            binding.checkBox2 -> {
                if(p1){
                    data += 10000
                }else{
                    data -= 10000
                }
            }
            binding.checkBox3 -> {
                if(p1){
                    data += 10000
                }else{
                    data -= 10000
                }
            }
        }
    }
}

 

(3-3) 리스너 연결 방식 3 : SAM 기법으로 구현

-Single Abstract Method

-람다 방식으로 간단하게 표현. 매개변수와 실행문만 있음.

 

-New Module lab06_1

└뷰바인딩 먼저 : build.gradle(Module : )

android {
...
    viewBinding{
        enabled=true
    }
}

└버튼 입력 - 위치 고정?(2방향) - textView의 id : textView

 

(4) 클릭 / 롱클릭 이벤트 처리

(4-1) 버튼 입력 및 textView id 설정

-[ Design ]에서 버튼 드래그, textView 아이디 입력

 

(4-2) MainActivity.kt

package com.example.lab06_1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.example.lab06_1.databinding.ActivityMainBinding

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

	//뷰 바인딩
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
	//클릭과 롱클릭
        binding.button.setOnClickListener {
            binding.textView.setText("버튼 클릭!")
        }
        binding.button.setOnLongClickListener {
            binding.textView.setText("Long~~~~~ Click")
            true //리턴 타입이 불리언이라 리턴타입을 붙여줘야 함.
        }
        //롱클릭 : 단축 메뉴사용할 때
    }
}

 

(5) 실습: 스톱워치 만들기

(5-1) drawable :img 등의 소스뿐만 아니라 xml 파일로도 만들 수 있음.

-New : drawable resource file - name : round_button(대문자 불가)

 

-round_button.xml 파일에서 [라운드 버튼] 만들기

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="10dp"
    android:shape="rectangle">
    <solid android:color="#01A9DB"/>
    <corners
        android:bottomLeftRadius="15dp"
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="15dp"/>
</shape>

└30은 너무 과해서 수정했음.

 

-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">
    <!--스톱워치-->
    <Chronometer
        android:id="@+id/chronemeter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:gravity="center_horizontal"
        android:textSize="60dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

>> 수평 레이아웃 입력

>> 버튼 3개 입력

[ Code ]에서 수정 : layout_weight="1" 삭제 / 위치 수정 / 만든 버튼 입력

-버튼 아이디 수정 및 버튼 내용(android:text) 수정

-enabled : 활성화/비활성화 - 기본값은 true

android:enabled="true | false"
<?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">
    <!--스톱워치-->
    <Chronometer
        android:id="@+id/chronemeter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:gravity="center_horizontal"
        android:textSize="60dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="1dp"
        android:layout_marginTop="60dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/chronemeter">

        <Button
            android:id="@+id/btnStart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/round_button"
            android:textColor="#ffffff"
            android:textSize="20dp"
            android:text="START" />

        <Button
            android:id="@+id/btnStop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/round_button"
            android:textColor="#ffffff"
            android:textSize="20dp"
            android:enabled="false"
            android:text="STOP" />

        <Button
            android:id="@+id/btnReset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/round_button"
            android:textColor="#ffffff"
            android:textSize="20dp"
            android:enabled="false"
            android:text="RESET" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

 

-MainActivity.kt

package com.example.lab06_1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.view.View
import com.example.lab06_1.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    //스톱워치를 위한 변수
    var iniTime = 0L //초기시간 저장하는 것.
    var pauseTime = 0L //일시정지했을 때 시간 저장하는 것

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

        //뷰 바인딩
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //스톱워치
        //start button 눌렀을 때 설정
        binding.btnStart.setOnClickListener {
            binding.chronometer.base = SystemClock.elapsedRealtime()+pauseTime //베이스 시간
            binding.chronometer.start()
            binding.btnStop.isEnabled = true
            binding.btnReset.isEnabled = true
            binding.btnStart.isEnabled = false
        }
        //Stop button 눌렀을 때 설정
        binding.btnStop.setOnClickListener {
            pauseTime = binding.chronometer.base - SystemClock.elapsedRealtime() //elapsedRealtime() 1/1000초
            binding.chronometer.stop()
            binding.btnStop.isEnabled = false
            binding.btnReset.isEnabled = true
            binding.btnStart.isEnabled = true
        }

        //Reset button 눌렀을 때 설정
        binding.btnReset.setOnClickListener {
            pauseTime = 0L
            binding.chronometer.base = SystemClock.elapsedRealtime()
            binding.chronometer.stop()
            binding.btnStop.isEnabled = false
            binding.btnReset.isEnabled = false
            binding.btnStart.isEnabled = true
        }
    }
}

 

(6) 실습 : 계산기

-activity_main.xml : 보여지는 것 그리기

<?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"
    android:paddingTop="30dp"
    tools:context=".test1.CalcActivity">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="4dp"
        android:gravity="right"
        android:text="0.0"
        android:paddingRight="15dp"
        android:textSize="25dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <GridLayout
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="1dp"
        android:layout_marginTop="11dp"
        android:orientation="horizontal"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2">

        <Button
            android:id="@+id/b1"
            android:layout_marginRight="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="0"
            android:layout_column="0"
            android:textSize="20dp"
            android:text="C" />

        <Button
            android:id="@+id/b2"
            android:layout_marginRight="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="0"
            android:layout_column="1"
            android:textSize="20dp"
            android:text="(" />

        <Button
            android:id="@+id/b3"
            android:layout_marginRight="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="0"
            android:layout_column="2"
            android:textSize="20dp"
            android:text=")" />

        <Button
            android:id="@+id/b4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="0"
            android:layout_column="3"
            android:textSize="20dp"
            android:text="+" />

        <Button
            android:id="@+id/b5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="1"
            android:layout_column="0"
            android:textSize="20dp"
            android:text="7" />

        <Button
            android:id="@+id/b6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="1"
            android:layout_column="1"
            android:textSize="20dp"
            android:text="8" />

        <Button
            android:id="@+id/b7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="1"
            android:layout_column="2"
            android:textSize="20dp"
            android:text="9" />

        <Button
            android:id="@+id/b8"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="1"
            android:layout_column="3"
            android:textSize="20dp"
            android:text="-" />

        <Button
            android:id="@+id/b9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="2"
            android:layout_column="0"
            android:textSize="20dp"
            android:text="4" />

        <Button
            android:id="@+id/b10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="2"
            android:layout_column="1"
            android:textSize="20dp"
            android:text="5" />

        <Button
            android:id="@+id/b11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="2"
            android:layout_column="2"
            android:textSize="20dp"
            android:text="6" />

        <Button
            android:id="@+id/b12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="2"
            android:layout_column="3"
            android:textSize="20dp"
            android:text="*" />

        <Button
            android:id="@+id/b13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="3"
            android:layout_column="0"
            android:textSize="20dp"
            android:text="1" />

        <Button
            android:id="@+id/b14"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="3"
            android:layout_column="1"
            android:textSize="20dp"
            android:text="2" />

        <Button
            android:id="@+id/b15"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="3"
            android:layout_column="2"
            android:textSize="20dp"
            android:text="3" />

        <Button
            android:id="@+id/b17"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="3"
            android:layout_column="3"
            android:textSize="20dp"
            android:text="/" />

        <Button
            android:id="@+id/b18"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="4"
            android:layout_column="0"
            android:textSize="20dp"
            android:text="%" />

        <Button
            android:id="@+id/b19"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="4"
            android:layout_column="1"
            android:textSize="20dp"
            android:text="0" />

        <Button
            android:id="@+id/b20"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="4"
            android:layout_column="2"
            android:textSize="20dp"
            android:text="." />

        <Button
            android:id="@+id/b21"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_row="4"
            android:layout_column="3"
            android:textSize="20dp"
            android:text="=" />
    </GridLayout>

</LinearLayout>

 

-CalcActivity.kt

package com.example.lab06_1.test1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import com.example.lab06_1.R
import com.example.lab06_1.databinding.ActivityCalcBinding
import java.util.*

class CalcActivity : AppCompatActivity() {
    //view Binding
    lateinit var binding: ActivityCalcBinding
    //Calculator Array
    lateinit var btnArray: Array<Button?>
    var resultStr = ""

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

        //view Binding
        binding = ActivityCalcBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //Calculator Array
        btnArray = arrayOf(binding.b1, binding.b2, binding.b3, binding.b4, binding.b5, binding.b6,
            binding.b7, binding.b8, binding.b9, binding.b10, binding.b11, binding.b12, binding.b13,
            binding.b14, binding.b18, binding.b19, binding.b20, binding.b21, binding.b25, binding.b27)

    //for문 Event 처리
        for(i in 0..19){
            btnArray[i]?.setOnClickListener { //이거 빠져서 계속 값을 못 가져왔던 것.
                var result = 0.0

                var str1 = btnArray[i]?.text  //전역 변수 btnArray 바로 가져와서 사용?
                when(str1){
                    "=" -> {
                        //먼저 토큰 생성
                        val tokStr = StringTokenizer(resultStr, "+-*/", true) //토크나이저, 구분자(로 문자열을 구분)
                        Log.d("parkA","tokStr:${tokStr.countTokens()}")

                    val num1 = tokStr.nextToken().toDouble()
                    var op = tokStr.nextToken()
                    var num2 = tokStr.nextToken().toDouble()
                    when(op){
                        "+" -> result = num1 + num2
                        "-" -> result = num1 - num2
                        "*" -> result = num1 * num2
                        "/" -> result = num1 / num2
                    }
                         binding.textView2.setText(result.toString()) //결과를 문자열로 바꿔서 넣음
                         resultStr = result.toString()
                    }
                    "C" -> {
                        resultStr=""
                        binding.textView2.setText("0.0")
                    }else -> {
                    resultStr += btnArray[i]?.text
                binding.textView2.setText(resultStr)
                }
                }
            }

        }
    }
}

 

>> 버튼 만들 때, 빵꾸나서 다시 만들었는데

그로 인해서 nullPoint 때문에 계속 안 되는 듯. 한번 만들 때, 충돌이 발생하면 계속 충돌 발생....

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함