안드로이드 코틀린 : CustomView 생성하여 화면 터치 위치 원 그리기
Lucy Archive
Lucy 2023
2021. 4. 12. 14:42

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

Gragle 수정 사항 적용

VIewBinding 설정 방법 및 Activity 및 Fragment에서 사용하는 방법은 아래의 링크를 참고해주세요.

안드로이드 View Binding 사용하기

 

안드로이드 View Binding 사용하기 - kotlin-android-extensions 지원 중단

안드로이드 View Binding 방법 정리 안드로이드 코드에서 레이아웃 View에 접근하기 위해 사용된 kotlin-android-extensions 의 지원이 중단예정으로, 이를 대체하여 사용 할 수 있는 ViewBinding 사용법에 대해

juahnpop.tistory.com

 

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() 를 호출합니다. 

PaintView 클래스 생성

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

 

실행 결과

위 코드를 실행하면 아래와 같이 터치하는 지점에 원이 생기고, 터치가 떨어지면 원이 사라지는 것을 확인 할 수 있습니다. 

실행 결과

끝까지 읽어 주셔서 감사합니다.^^

관련포스트

🤞 안드로이드(코틀린) 앱 제작하기 관련글 목록 보기

🤞 안드로이드(코틀린) 커스텀뷰 관련글 목록 보기