국비교육(22-23)

72일차(4)/Android App(20) : Custom View

서리/Seori 2023. 1. 19. 01:06

72일차(3)/Android App(20) : Custom View

 

- 새 모듈 생성

step09customview

 

- MainActivity 수정없음

 

- View를 상속받아서 나만의 뷰 만들기!

- View 안의 동작을 마음대로 설정할 수 있다.

 

MyView

package com.example.step09customview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class MyView extends View {
    //색상을 나타내는 정수값을 미리 int[]에 준비하고
    int[] colors={Color.GREEN, Color.RED, Color.BLUE};
    //인덱스로 사용할 필드
    int index;
    //이미지의 위치 초기값
    int x=100;

    //생성자1
    public MyView(Context context) {
        super(context);
    }
    //생성자2
    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    //View 가 차지하고 있는 화면에 Canvas 객체를 이용해서 그림 그리기(화면 구성하기)
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(colors[index]);
        //BitmapFactory 클래스의 static 메소드를 이용해서 이미지 로딩해서
        //Bitmap type으로 만들기
        Bitmap image= BitmapFactory.decodeResource(getResources(), R.drawable.korea);
        //Bitmap의 크기를 변환하기
        Bitmap scaledImage=Bitmap.createScaledBitmap(image,100,100,false);
        //canvas 객체를 이용해서 이미지의 최상단의 좌표를 지정하고 그린다.
        canvas.drawBitmap(scaledImage,x,100,null);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //인덱스를 1 증가시키고
        index++;
        //만일 없는 인덱스라면
        if(index==3){
            index=0; //0으로 초기화하기
        }
        //x를 10씩 증가시킨다.
        x += 10;

        //화면 갱신하는 메소드 호출!(결과적으로 View가 무효화되고 onDraw() 가 다시 호출
        invalidate();
        return super.onTouchEvent(event);
    }
}

 

- View를 상속하고, 생성자를 가져와주어야 한다!

- 생성자 2개를 상속하고 onDraw 메소드 오버라이드하기

 

- 이런 View가 만들어지는 것! 색상이 연두색인 view. 아직 아무 동작도 없다.

 

 

activity_main.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">

    <com.example.step09customview.MyView
        android:layout_width="match_parent"
        android:layout_height="300dp"/>

</LinearLayout>

 

- myView를 가져와주기

 

- 단순히 이렇게 생긴 뷰이다.

 

invalidate() 메소드 추가

- 뷰에 어떤 이벤트가 일어나면 자동으로 호출된다.

- 터치가 일어나면 뷰가 무효화되고 다시 호출된다.

 

- 필드에다가 int배열, int필드 만들기

- 터치할 때마다 색이 바뀌게 만들 예정!

 

- 터치할 때마다 인덱스가 1씩 증가하고, 2에서 터치하면 다시 0이 된다.

 

- 터치하면 색상이 바뀐다.

- 많은 게임들이 이런 방식으로 작동된다.

 

- 이미지를 그릴 수도 있다.

- korea.png 이미지를 하나 넣어주기

 

- 이렇게 코딩하면 좌상단에 korea 이미지를 출력할 수 있다.

 

 

- 만약 클릭할때마다 이미지가 이동하며 10씩 움직이게 하고 싶다면?

 

- 이 이미지의 위치를옮기려면?

- left 값을 필드(x)로 만들어놓고 초기값(100) 넣어주기

- 터치할때마다 이 x가 10씩 증가하도록 설정해준다.

 

- 클릭하면 색도 바뀌고, 10씩 옆으로 이동한다.

- 게임도 이런 방식으로 View 화면을 제어하는 것으로 만들 수 있다.

 

 

- 캔버스의 메소드를 활용해서 화면구성을 할 수 있다.

 

- 화면을 업데이트하고 싶으면 적절한 때에 invalidate 하면 된다.