GDSC HUFS 4기/Kotlin Team #6

[6팀] 드로잉 앱 - 드로잉 뷰, 브러쉬, DisplayMatrix

백거누 2022. 11. 14. 20:11

 

이 글은 유데미 강의 Android 12 및 Kotlin 개발 완전 정복을 참고하여 작성하였습니다.

작성자 : 백건우

개발환경은 Windows, Android Studio입니다.

 

114-120강의 내용입니다.

 

먼저 AndroidManifest.xml에서 android:screenOrientation="portrait"으로 설정하여 앱이 항상 세로로 보이도록 고정한다.

1. Drawing View

Drawing View는 kids drawing app을 만들기 위해 선언한 class 이다.

# activity로 사용하지 않는 이유

  • MainActivity에 있는 AppCompatActivity에 있는 기능을 사용하기 위해서이다.
  • 무언가를 그리려면 View type을 사용해야 하기 때문이다.

아래와 같이 View 클래스를 상속받으면 커스텀 클래스를 View로 사용할 수 있다.

  • Bitmap : 안드로이드에서 이미지를 표현하기 위해 사용하는 클래스
  • Paint : 안드로이드에서 geometry, text, bitmap 등의 색상이나 스타일 등을 저장하는 클래스
class DrawingView(context:Context,attrs:AttributeSet) : View(context ,attrs){
    private var mDrawPath: CustomPath?=null       // 사용자가 그린 그림을 저장할 변수
    private var mCanvasBitmap : Bitmap?=null      // bitmap 변수
    private var mDrawPaint: Paint?= null          // 그림의 paint 변수
    private var mCanvasPaint : Paint?=null        // 캔버스의 paint 변수
    private var mBrushSize : Float = 0.toFloat()  // 브러쉬 크기 변수
    private var color = Color.BLACK               // 브러쉬 색상 변수
    private var canvas : Canvas?=null             // 캔버스 변수
    private var mPaths = ArrayList<CustomPath>()  // 그림 리스트(이전에 그린 것이 사라지지 않게 하기 위해 사용)

    init {
          setUpDrawing()
    }
    private fun setUpDrawing(){ // 위에서 설정한 변수들의 초기값을 설정해주는 함수
        mDrawPaint= Paint()
        mDrawPath = CustomPath(color,mBrushSize)
        mDrawPaint!!.color=color
        mDrawPaint!!.style=Paint.Style.STROKE
        mDrawPaint!!.strokeJoin=Paint.Join.ROUND
        mDrawPaint!!.strokeCap=Paint.Cap.ROUND
        mCanvasPaint= Paint(Paint.DITHER_FLAG)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    	// 화면 크기가 바뀔 때 호출되는 함수
        super.onSizeChanged(w, h, oldw, oldh) 
        mCanvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888)
        canvas= Canvas(mCanvasBitmap!!)
    }

    override fun onDraw(canvas: Canvas) {
    	// 무언가가 그려졌을 때 호출되는 함수
        // 사용자가 그린 그림을 화면에 나타낸다.
        super.onDraw(canvas)
        canvas.drawBitmap(mCanvasBitmap!!,0f,0f,mCanvasPaint)
        for(path in mPaths){
            mDrawPaint!!.strokeWidth = path.brushThickness
            mDrawPaint!!.color= path.color
            canvas.drawPath(path ,mDrawPaint!!)
        }
        if (!mDrawPath!!.isEmpty){
            mDrawPaint!!.strokeWidth = mDrawPath!!.brushThickness
            mDrawPaint!!.color= mDrawPath!!.color
            canvas.drawPath(mDrawPath!!,mDrawPaint!!)
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
    	// 화면에 터치가 발생했을 때 호출되는 함수
        val touchX=event?.x
        val touchY=event?.y
        when(event?.action){
            MotionEvent.ACTION_DOWN ->{ // 화면이 눌렸을 때
                mDrawPath!!.color = color
                mDrawPath!!.brushThickness = mBrushSize
                mDrawPath!!.reset()
                if (touchX != null) {
                    if (touchY != null) {
                        mDrawPath!!.moveTo(touchX,touchY)
                    }
                }
            }
            MotionEvent.ACTION_MOVE -> { // 터치된 상태로 움직일 때
                if (touchX != null) {
                    if (touchY != null) {
                        mDrawPath!!.lineTo(touchX, touchY)
                    }
                }
            }
            MotionEvent.ACTION_UP ->{ // 터치가 종료되었을 때
                mPaths.add(mDrawPath!!)
                mDrawPath = CustomPath(color,mBrushSize)
            }
            else  -> return false
        }
        invalidate()
        return true
    }
}

2. 캔버스 가장자리에 회색 테두리 설정하기

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#FFFFFF" /> // 흰색

    <stroke
        android:width="0.5dp"         // 테두리 두께
        android:color="#9AA2AF" />    // 테두리 색 설정
</shape>

3. 브러쉬 크기 설정

// DrawingView의 맴버 함수

fun  setSizeForBrush(newSize: Float){
        mBrushSize = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,        // 사용할 단위
        newSize, resources.displayMetrics)  // 정보값, 측정기준(실행중인 화면크기에 비례)
        mDrawPaint!!.strokeWidth=mBrushSize // 브러쉬 크기 업데이트
}
// Mainactivity.kt
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
	
    private var drawingView: DrawingView? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        drawingView = findViewById(R.id.drawing_view) // DrawingView 인스턴스 id로 탐색
        drawingView?.setSizeForBrush(20.toFloat())    // 브러쉬 크기 설정
    }

}