본문 바로가기
안드로이드 자바

[JAVA][Android] Canvas, Paint를 이용해 그림판 만들기

by teamnova 2022. 10. 2.

안녕하세요.

오늘은 canvas와 paint를 이용해 간단한 그림판을 만들겠습니다.

 

먼저 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=".MainActivity"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#cccccc"
        android:orientation="horizontal">
        <EditText
            android:inputType="number"
            android:gravity="center_horizontal"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            android:textSize="15dp"
            android:text="10"
            android:id="@+id/editTextSize"/>
        <TextView
            android:layout_marginTop="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="px"
            android:textSize="15dp"
            android:textColor="@color/black"/>
        <RadioGroup
            android:layout_margin="15dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/radioGroup">
            <RadioButton
                android:checked="true"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:textSize="15dp"
                android:text="검정"
                android:id="@+id/btnBlack"/>
            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:textSize="15dp"
                android:text="빨강"
                android:id="@+id/btnRed"/>
            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:textSize="15dp"
                android:text="파랑"
                android:id="@+id/btnBlue"/>
            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:textSize="15dp"
                android:text="지우개"
                android:id="@+id/btnEraser"/>

        </RadioGroup>
        <Button
            android:layout_marginTop="5dp"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:text="clear"
            android:textSize="8dp"
            android:id="@+id/btnClear"/>


    </LinearLayout>

    <LinearLayout
        android:id="@+id/paintLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"/>



</LinearLayout>

다음으로 자바파일입니다.

import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;

public class MainActivity extends AppCompatActivity {
    private MyPaintView myView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("내 그림판");
        myView = new MyPaintView(this);
        
        
        //펜색 및 지우개 선택하기
        ((LinearLayout) findViewById(R.id.paintLayout)).addView(myView);
        ((RadioGroup)findViewById(R.id.radioGroup)).setOnCheckedChangeListener(
                new RadioGroup.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
                        switch (checkedId) {
                            case R.id.btnBlack:
                                myView.mPaint.setColor(Color.BLACK);
                                break;
                            case R.id.btnRed:
                                myView.mPaint.setColor(Color.RED);
                                break;
                            case R.id.btnBlue:
                                myView.mPaint.setColor(Color.BLUE);
                                break;
                            case R.id.btnEraser:
                                myView.mPaint.setColor(Color.WHITE);
                                break;
                        }
                    }
                });
        
        //펜 크기 설정
        EditText editTextSize = (EditText)findViewById(R.id.editTextSize);
        editTextSize.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                if(i == KeyEvent.KEYCODE_ENTER){
                    String inputTextSize = editTextSize.getText().toString();
                    if(inputTextSize.equals("")){ //아무 숫자 입력이 없을 때 10px로 설정
                        editTextSize.setText("10");
                        myView.mPaint.setStrokeWidth(10);
                    }else { //입력한 숫자에 맞게 크기 설정
                        myView.mPaint.setStrokeWidth(Integer.parseInt(inputTextSize));
                    }
                }
                return false;
            }
        });
        
        //그림판 초기화
        ((Button)findViewById(R.id.btnClear)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                myView.mBitmap.eraseColor(Color.TRANSPARENT);
                myView.invalidate();
            }
        });
    }

    private static class MyPaintView extends View {
        private Bitmap mBitmap;
        private Canvas mCanvas;
        private Path mPath;
        private Paint mPaint;
        public MyPaintView(MainActivity context) {
            super(context);
            mPath = new Path();
            mPaint = new Paint();
            mPaint.setColor(Color.BLACK);
            mPaint.setAntiAlias(true);
            mPaint.setStrokeWidth(10);
            mPaint.setStyle(Paint.Style.STROKE);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, 0, 0, null); //지금까지 그려진 내용
            canvas.drawPath(mPath, mPaint); //현재 그리고 있는 내용
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int x = (int)event.getX();
            int y = (int)event.getY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mPath.reset();
                    mPath.moveTo(x, y);
                    break;
                case MotionEvent.ACTION_MOVE:
                    mPath.lineTo(x, y);
                    break;
                case MotionEvent.ACTION_UP:
                    mPath.lineTo(x, y);
                    mCanvas.drawPath(mPath, mPaint); //mBitmap 에 기록
                    mPath.reset();
                    break;
            }
            this.invalidate();
            return true;
        }
    }
}

 

실행화면입니다.

 

보시다시피 선택한 색깔과 입력한 사이즈에 맞게 그림이 그려지는 모습입니다.

 

궁금한 점은 댓글로 남겨주세요.

감사합니다.