Le_Penseur

[안드로이드 스튜디오] Ch18. 그림판 만들기 (Canvas View) 본문

개인(Personal)/안드로이드 (Andorid Studio)

[안드로이드 스튜디오] Ch18. 그림판 만들기 (Canvas View)

LePenseur 2019. 9. 8. 21:23
반응형

2019년 9월08일 (일)




*질적으로 많이 부족한 글입니다. 지적 및 조언 환영합니다.
*이 글에선 "안드로이드 스튜디오"를 줄여서 "안스" 라고 표현합니다. 참고 바랍니다.

우선, 본인은 학원에서 'JAVA' 기초 수업을 선수강했다. 안드로이드 스튜디오를 배우기 위해선 피할 수 없는 언어이기 때문이다.


잡담: 좋아! 일요일이니까 오전부터해서 하루종일 공부해야지! ...라고 다짐했지만 푹~ 쉬어주고 오후8시부터 포스팅 작성이 시작된다.
...역시 내인생이 레전드다.


저번 포스팅에서 언급한것과 같이 이번 포스팅도 역시 하나의 프로젝트 내에서 상당히 긴 코드들이 나오기에 한 포스팅당 하나의 프로젝트만 다룰 예정이다.

우선, 이번글의 중요포인트 4가지를 짚고 넘어가자.

(1) Path - 자바의 buffer와 비슷함. 즉, 쉽게 말해 '저장공간' 정도.
(2) Paint - 페인트 메소드를 호출함.
(3) int x,y - 페인트가 손가락 터치를 따라가기 위한 좌표 생성
(4) onDraw (Canvas canvas) - 캔버스에서 그림 그리기를 처리해주는 메소드 생성.


<차례>
1. MyCanvasActivity


1. MyCanvasActivity
1.1 결과
사진1. 화면안에서 그림을 그린모습
사진2. 화면을 가로로 돌린 모습.

설명: 이번 프로젝트는 간단하다면 간단하다. 그래서 간단하게 구호로 설명한다.
페인트 호출! 경로 호출! 메모리 호출! 캔버스 호출! -끝-
물론 덧붙이자면 엑티비티의 방향이 바뀔때마다 Toast로 '가로' '세로'를 띄워줘야 하는 것도 있지만
그러한 자세한 설명은 밑의 코드와 함께 따라가보자.

1.2 코드
1.21 MainActivity.java
package com.example.mycanvasactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.Toast;

//그림을 그리는 Canvas , Paint 객체를 사용하여 그려보자...

//그림판 앱....

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       // setContentView(R.layout.activity_main);

        setContentView(new MyView(this));

        //디바이스 회전시 값 유지를 하기위한 코드
        Resources r = Resources.getSystem();
        Configuration config = r.getConfiguration();
        onConfigurationChanged(config);

        //onConfigurationChanged
        //오버라이드를 했을경우 회전시마다 onCreate메소드를 호출하므로
        // 재호출 하지 않도록 manifest에 속성두가지를 추가해주면된다..
//        android:configChanges="orientation|keyboardHidden|screenSize"
//        android:windowSoftInputMode="stateHidden|adjustPan"
        //actitvy가 여러개라면 모든 액티비티에 속성을 추가해주는것이 좋다...
        
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        //현재 디바이스의 방향성을 체크...

        switch(newConfig.orientation){
            case Configuration.ORIENTATION_LANDSCAPE:
                Toast.makeText(getApplicationContext(),"가로",Toast.LENGTH_SHORT).show();
                break;
            case Configuration.ORIENTATION_PORTRAIT:
                Toast.makeText(getApplicationContext(),"세로",Toast.LENGTH_SHORT).show();
                return;
        }

    }
}


설명: 눈치챘는가? MainActivity내에서 그어떠한 메소드도 그림그리기와 관련된건 일절 없다.
그렇다. 그림과 관련된 메소드는 모두 외부 자바 클래스에서 만든다는것이다.
그리고 그 클래스를 MainActivity는 [setContentView]로 인플레이트 하여 호출만 해줄것이다.
that's it!
물론 엑티비티의 방향전환 및 토스트와 관련된 메소드는 위의 코드를 살펴보길 바란다.

1.22 MyView.java
package com.example.mycanvasactivity;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View {

    private Paint paint = new Paint();


    //여러가지의 그리기 명령을 모았다가 한번에 출력해주는
    //버퍼역할을 담당한다..
    private Path path = new Path();

    private int x,y;

    public MyView(Context context){

        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        paint.setColor(Color.BLACK);

        //STROKE속성을 이용하여 테두리...선...
        paint.setStyle(Paint.Style.STROKE);

        //두께
        paint.setStrokeWidth(3);


        //path객체가 가지고 있는 경로를 화면에 그린다...
        canvas.drawPath(path,paint);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int)event.getX();
        y = (int)event.getY();

        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                path.moveTo(x,y);
                break;
            case MotionEvent.ACTION_MOVE:
                x = (int)event.getX();
                y = (int)event.getY();

                path.lineTo(x,y);
                break;
        }

        //View의 onDraw()를 호출하는 메소드...
        invalidate();

        return true;
    }
}


설명: 순서에 따라 설명해보려 한다.

(1) 페인트, 메모리, 좌표, 엑티비티 총 4개의 변수 선언!

private Paint paint = new Paint();
    
private Path path = new Path();

private int x,y;

public MyView(Context context){
super(context);}


(2) onDraw (Canvas canvas) { }
- 캔버스를 호출하며 이 안에서 다양한 페인트 특성을 설정한다. 예를 들어 펜의 선 두께와 컬러 등.

@Override
    protected void onDraw(Canvas canvas) {

        paint.setColor(Color.BLACK);

        //STROKE속성을 이용하여 테두리...선...
        paint.setStyle(Paint.Style.STROKE);

        //두께
        paint.setStrokeWidth(3);

        //path객체가 가지고 있는 경로를 화면에 그린다...
        canvas.drawPath(path,paint);

    }


(3) onTouchEvent (MotionEvent event) {}
- 터치상태일때의 이벤트를 설정해주는 메소드다. 바로 여기에서 위에서 설정해준 경로변수 x,y 와 메모리변수 path 를 이용한다.
- 스위치문을 통해서 터치를 했을때 (DOWN) 와 터치를 멈췄을때(UP) 로, 즉 터치 이벤트 각각의 케이스별로 나누어준다.
- 터치를 했을때는 x,y 좌표가 움직이는 방향으로 path에 저장 || 터치가 움직일땐 이 모든 x,y좌표값을 int형으로 get함
- 결론적으로는 터치가 되는 시점부터 움직이는 모든 이벤트 동안의 좌표는 모두 int형으로 path안에 저장된다는 의미이다.

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int)event.getX();
        y = (int)event.getY();

        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                path.moveTo(x,y);
                break;
            case MotionEvent.ACTION_MOVE:
                x = (int)event.getX();
                y = (int)event.getY();

                path.lineTo(x,y);
                break;
        }


(4) invalidate();
- 화면을 갱신, 또는 초기화 하는 메소드다.

 invalidate();

        return true;

반응형
Comments