그래픽


그래픽 개요


1. 간단한 도형 그리기

  1. 뷰(View)를 상속한 클래스 정의

    public class CustomView extends View {
        // Simple constructor to use when creating a view from code
        public CustomView(Context context) {
            super(context);
        }   
    
        // Constructor that is called when inflating a view from XML
        public CustomView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
    }
  2. 페인트 객체 초기화 (색상, 선 스타일, 선 굵기 등 설정)

    public class CustomView extends View {
        private Paint paint;
    
        public CustomView(Context context) {
            super(context);
            init();
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs)) {
            super(context);
            init();
        }
    
        // 페인트 객체 초기화
        public void init() {
            paint = new Paint();
            paint.setColor(Color.RED);
        }
  3. View.onDraw() 메소드 내에서 도형 그리기

    public class CustomView extends View {
        //...생략...
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawRect(100, 100, 200, 200, paint);
        }
    }
  4. 새로 만든 뷰를 액티비티 레이아웃에 추가하기

    <com.kwanwoo.android.graphicstest.CustomView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/customView"
     />

    [주의] XML 레이아웃에 추가하기 위해서는 생성자 중에서 public CustomView(Context context, @Nullable AttributeSet attrs)가 반드시 재정의 되어야 함


2. 비트맵 이미지 그리기


3. 그래픽 애니메이션

  1. 화면에 터치 시에 볼 생성
  2. 볼은 임의의 방향과 속도로 움직이다가 벽에 부딪히면 반사

3.1 볼 클래스 정의


3.2 View 터치시 볼 생성 및 그리기

  1. View 터치 시
  2. 터치 위치에 볼 생성하여 arBall 리스트에 추가
  3. onDraw() 간접 호출
  4. arBall 리스트에서 볼을 추출
  5. 추출된 볼을 캔버스에 그림
public class AnimatedView extends View {
    private ArrayList<Ball> arBall = new ArrayList<Ball>();
    ...
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int idx=0; idx<arBall.size(); idx++) {
            Ball B = arBall.get(idx);  // 4. arBall 리스트에서 볼을 추출
            B.draw(canvas);            // 5. 추출된 볼을 캔버스에 그림
        }
    }
    public boolean onTouchEvent(MotionEvent event) {
        // 1. View 터치 시
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // 2. 터치 위치에 볼 생성하여 arBall 리스트에 추가
            arBall.add(new Ball((int)event.getX(), (int)event.getY()));
            invalidate();  // 3. onDraw() 간접 호출
            return true;
        }
        return false;
    }
}

https://github.com/kwanulee/Android/blob/master/examples/GraphicsTest/app/src/main/java/com/kwanwoo/android/graphicstest/AnimatedView.java#L34-L53


3.3 볼 애니메이션

public class AnimatedView extends View {
    private ArrayList<Ball> arBall = new ArrayList<Ball>();
    ...
    public void updateAnimation() {
        for (int idx=0; idx<arBall.size(); idx++) {
            Ball B = arBall.get(idx);    // 3. arBall 리스트에서 볼을 추출
            B.move(getWidth(),getHeight());  // 4. 추출된 볼을 애니메이트
        }
        invalidate();  // 5. 다시 onDraw() 간접 호출 (무한 반복)
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 1. arBall 리스트에 있는 모든 Ball 객체 그리기
        for (int idx=0; idx<arBall.size(); idx++) {
            Ball B = arBall.get(idx);
            B.draw(canvas);
        }
        updateAnimation(); // 2. updateAnimation 메소드 호출
    }

https://github.com/kwanulee/Android/blob/master/examples/GraphicsTest/app/src/main/java/com/kwanwoo/android/graphicstest/AnimatedView.java#L55-L61


4. SurfaceView 이용한 그래픽 애니메이션

4.1 SurfaceView 클래스 정의

public class AnimatedSurfaceView extends SurfaceView  
                                implements SurfaceHolder.Callback
    
    // Constructor that is called when inflating a view from XML
    public AnimatedSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    // SurfaceHolder.Callback 인터페이스 구현
    public void surfaceCreated(SurfaceHolder surfaceHolder) { /*...*/ }
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { /*...*/ }
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) { /*...*/ }


}

4.2 SurfaceView 사용 설정

public class AnimatedSurfaceView extends SurfaceView  
                                implements SurfaceHolder.Callback
                                
    SurfaceHolder holder;                            
                                           
    public AnimatedSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        holder = getHolder();       // SurfaceHolder 객체 획득
        holder.addCallback(this);   // SurfaceHolder 객체에 SurfaceHolder.Callback 인터페이스 구현을 등록
        //...
    }
    // ...

4.3 SurfaceView에 그래픽 그리기

    private void draw() {
        while (true) {
            //1. 볼을 그릴 캔버스를 lockCanvas() 메소드를 통해 참조하고 캔버스에 락을 걸어 둠
            Canvas canvas  = holder.lockCanvas(null);

            //2. 앞에서 얻은 캔버스에 모든 볼을 이동시키고 그림
            canvas.drawColor(Color.WHITE); // cavas 지우기- 흰색으로 채우기
            synchronized (holder) {
                for (int idx=0; idx<arBall.size(); idx++) { 
                    Ball B = arBall.get(idx);
                    B.move(getWidth(),getHeight());
                    B.draw(canvas);
                }
            }

            // 3. 캔버스 객체에 락을 풀어줌
            holder.unlockCanvasAndPost(canvas);
        }
    }   
public class AnimatedSurfaceView  extends SurfaceView // SurfaceView 상속
                    implements SurfaceHolder.Callback {

    private Thread thread;
    //...

    public AnimatedSurfaceView(Context context, AttributeSet attrs) {
        //...

        thread = new Thread() {
            public void run() {
                draw();  // 볼 애니메이션 
            }
        };
    }

    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        thread.start();
    }

    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}

    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        try {
            thread.join();
        } catch (InterruptedException e) {}
    }

주의 메인 스레드와 별도의 스레드에서 볼 애니메이션을 수행

https://github.com/kwanulee/Android/blob/master/examples/GraphicsTest/app/src/main/java/com/kwanwoo/android/graphicstest/AnimatedSurfaceView.java