Android Kotlin : Draw Circle on Touched Position with Custom View
터치된 위치에 원을 그리기 위해 CustomView를 제작 후 터치이벤트를 등록하는 방법
입니다.
프로젝트 생성 및 환경설정
앱 화면을 터치한 위치에 동그라미를 표시하는 예제입니다. 결과는 포스트의 하단에 있으니 참고해주세요.
프로젝트 생성
아래와 같이 프로젝트를 생성 합니다. 본 포스트의 코드는 Android Studio(4.1.2), Kotlin(1.4.31) 버전에서 작성하였습니다.
- 템플릿 : Empty Activity
- 프로젝트명 : CustomViewTouchedPosition
- 언어 : Kotlin
ViewBInding 설정
Layout에 있는 View의 Id를 이용하여 코드와 바인딩 하기 위해 App > Gradle Scripts > build.gradle에서 ViewBinding 설정 코드를 추가합니다. 코드 추가 완료되면 Sync Now를 클릭하여 변경 사항을 적용 합니다.
android {
...
viewBinding {
enabled = true
}
}
VIewBinding 설정 방법 및 Activity 및 Fragment에서 사용하는 방법은 아래의 링크를 참고해주세요.
Custom View 생성
PaintView.kt 코드 작성
CustomView를 생성하기 위해 PaintView란 이름의 클래스를 만들고 PaintView.kt 파일에 아래와 같이 코드를 입력 합니다. CustomView를 만들기 위해 View 클래스를 상속받고, onTouch 리스너를 등록하기 위해 View.OnTouchListener 인터페이스를 등록합니다. PaintView에 터치되면(MotionEvent.ACTION_DOWN) xAsix, yAsix에 클릭된 좌표값을 입력하고 onDraw() 를 호출합니다. 터치가 떨어지면(MotionEvent.ACTION_UP) xAsix, yAsix에 -100(화면 밖)을 입력하고 onDraw()를 호출합니다. invalidate() 메서드는 onDraw() 를 호출합니다.
package com.blacklog.customviewtouchedposition
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
class PaintView: View, View.OnTouchListener {
constructor(context : Context) : this(context, null)
constructor(context : Context, attrs : AttributeSet?): this(context, attrs, 0)
constructor(context : Context, attrs : AttributeSet?, defStyle: Int ): super(context, attrs, defStyle)
var paint : Paint? = null
var xAxis : Float? = null
var yAxis : Float? = null
init {
paint = Paint()
xAxis = -100F
yAxis = -100F
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when(event?.action){
MotionEvent.ACTION_UP -> {
xAxis = -100F
yAxis = -100F
invalidate()
}
MotionEvent.ACTION_DOWN -> {
xAxis = event.x
yAxis = event.y
invalidate()
}
}
return true
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
paint?.style = Paint.Style.STROKE
paint?.strokeWidth = 5F
paint?.color = Color.BLUE
canvas?.drawCircle(xAxis!!, yAxis!!, 50F, paint!!)
}
}
※ Custom View의 생성자(constructor) 종류는 3가지가 있는데 쓰임새는 아래와 같습니다. 본 포스트에서는 XML에 CustomView를 사용해서 지정된 attribute가 있으므로, Context와 AttributeSet 을 사용하는 두번째 생성자가 사용됩니다.
- Context만 사용
- 프로그래밍 코드에서만 생성(사용)하는 CustomView
- XML에 접근하지 않고, 레이아웃 관련된 모든 속성을 코드로 작성해야 함
- Context, AttributeSet
- XML 레이아웃 파일에 있는 속성에 접근해서 사용
- AttributeSet을 선언자로 지정하지 않으면 layout inflater 에러 발생
- Context, AttributeSet, DefStyle
- 스타일/테마 속성을 참조해야 할때 사용되는 생성자
레이아웃 작성
activity_main.xml 코드 작성
activity_main.xml에서 위에서 커스텀으로 제작한 PaintView를 추가합니다.
<?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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.blacklog.customviewtouchedposition.PaintView
android:id="@+id/paintView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity에서 커스텀뷰의 리스너 등록
MainActivity.kt 코드 작성
MainActivity에서 PaintView 클래스에 사용된 onTouchListener 사용을 등록하기 위해 아래와 같이 코드를 작성합니다. 아래 코드에서 setOnTouchListner를 등록하기 위해 PainView 클래스에서 View.OnTouchListener 인터페이스를 사용하였습니다.
package com.blacklog.customviewtouchedposition
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.blacklog.customviewtouchedposition.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.paintView.setOnTouchListener(binding.paintView)
}
}
실행 결과
위 코드를 실행하면 아래와 같이 터치하는 지점에 원이 생기고, 터치가 떨어지면 원이 사라지는 것을 확인 할 수 있습니다.
끝까지 읽어 주셔서 감사합니다.^^
'Programming > Android App(Kotlin)' 카테고리의 다른 글
안드로이드 코틀린 : 일반 클래스에서 Fragment의 메서드 사용하기 (0) | 2021.04.17 |
---|---|
안드로이드 코틀린 : JetPack Navigation로 Fragment 전환 및 데이터 전송 기본 사용법 (0) | 2021.04.13 |
안드로이드 코틀린 : RecyclerView Item 버튼 이벤트 추가 하기(with ViewBinding) (0) | 2021.04.10 |
안드로이드 코틀린 : imageView에 올바르게 회전 된 Bitmap 삽입하기(with CameraX) (0) | 2021.04.10 |
안드로이드 코틀린 : 사진의 Exif 데이터 읽기, 쓰기 - ExifInterface (0) | 2021.04.08 |