GDSC HUFS 4기/Kotlin Team #2

[2팀] 드로잉 앱 만들기 (1)

ヽ(°ᴥ°)ノ 2022. 11. 15. 16:13

 

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

작성자 : 유희수

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

 

1. 드로잉 뷰 변수 세팅

  • 항상 세로로 화면 고정
    • android:screenOrientation =”portrait”
  • View 타입
    • 뭔가 그리고 싶을때 사용하는 타입 → view type 선언
  • Bitmap 
    • 비트맵(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 변수
    
    // Paint : geometry, text, 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 val mPaths = ArrayList<CustomPath>() // 그릴때마다 그 값을 계속 보이게하기 위해 
	
    // 위에 선언한 변수에 초기값 할당
    init {
        setUpDrawing()
    }

    private fun setUpDrawing() {
        mDrawPaint = Paint()
        mDrawPath = CustomPath(color, mBrushSize)
        mDrawPaint!!.color = color
        mDrawPaint!!.style = Paint.Style.STROKE // This is to draw a STROKE style
        mDrawPaint!!.strokeJoin = Paint.Join.ROUND // This is for store join
        mDrawPaint!!.strokeCap = Paint.Cap.ROUND // This is for stroke Cap
        mCanvasPaint = Paint(Paint.DITHER_FLAG) // Paint flag that enables dithering when blitting.
		
    }
	
    
    // path클래스는 직선, 2차곡선, 3차곡선 등으로 구성되어 그리거나, 자르는 등의 작업을 수행하는데 사용할 수 있다
    internal inner class CustomPath(var color:Int,var brushThickness:Float):Path()
}

 

2. 뷰 파트에서 기능 추가

1) 뷰의 크기가 변경 됐을때마다 불러오는 함수 

// 뷰의 크기가 변경되었을 때 레이아웃 안에 설정됨
    override fun onSizeChanged(w: Int, h: Int, wprev: Int, hprev: Int) {
        super.onSizeChanged(w, h, wprev, hprev)
        // 화면의 크기가 변경될 때 bitmap을 표시하도록 해야 뷰에 뭔가를 표시할 수 있음
        mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888) // 특정 너비, 높이, 배열 지정
        canvas = Canvas(mCanvasBitmap!!)
    }

 

2) 그림 그릴 때 호출되며, 이때 사용할 도구에 대한 세팅을 해주는 함수 

override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        mCanvasBitmap!!.let {
            canvas.drawBitmap(it, 0f,   0f, mCanvasPaint) //  왼쪽 상단 기준으로 그림
        }

		// 브러쉬 두께 설정
        for (p in mPaths) {
            mDrawPaint?.strokeWidth = p.brushThickness
            mDrawPaint?.color = p.color
            canvas.drawPath(p, mDrawPaint!!)
        }
		
        if (!mDrawPath!!.isEmpty) {
            mDrawPaint?.strokeWidth = mDrawPath!!.brushThickness
            mDrawPaint?.color = mDrawPath!!.color
            canvas.drawPath(mDrawPath!!, mDrawPaint!!)
        }
    }

 

3) 스크린 터치할때 이벤트 설정

  • 터치 시작
  • 드래그
  • 터치 종료 → 터치 시작부터 종료될때까지 그린 선을 배열에 담아 놓는다
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() // Clear any lines and curves from the path, making it empty.
                mDrawPath?.moveTo(
                    touchX,
                    touchY
                ) // Set the beginning of the next contour to the point (x,y).
            }

            MotionEvent.ACTION_MOVE -> { // 드래그할 때
                mDrawPath?.lineTo(
                    touchX,
                    touchY
                ) // Add a line from the last point to the specified point (x,y).
            }

            MotionEvent.ACTION_UP -> { // 터치 종료

                mPaths.add(mDrawPath!!) //Add when to stroke is drawn to canvas and added in the path arraylist

                mDrawPath = CustomPath(color, mBrushSize)
            }
            else -> return false
        }

        invalidate()
        return true
    }

 

4) 브러쉬 크기, 색상 변경

fun setSizeForBrush(newSize: Float) {
    mBrushSize = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP, // 픽셀 크기
        newSize, 변경할 두께
        resources.displayMetrics // 화면 크기 고려해서 두께 설정
    )
    mDrawPaint?.strokeWidth = mBrushSize
}

fun setColor(newColor: String) {
    color = Color.parseColor(newColor)
    mDrawPaint?.color = color
}