Dev./Android

즉석 복권 같은 스크래치(Scratch) 효과를 주는 뷰

like miller 2012. 7. 23. 19:51

흔히 볼 수 있는 즉석 복권 같이 긁으면 위에 붙어 있는 것이 떨어지고 밑에 있는 내용이 보이는 이런 효과를 구현 커스텀 뷰를 소개한다.

이미지 2장을 겹친 후 위에 것을 지우는 듯한 효과를 가졌다. 맞는지는 모르지만 일단 scratch 효과라고 해 두겠다.


*실제 즉석 복권 사진


*아이폰 어플로 구현 scratch 효과



1. Scratch 효과 개념 설명.

1. 2개의 비트맵을 가지고 있는다. (a, b)

2. a 비트맵을 먼저 그려서 보여준다

3. 사용자의 터치한 곳의 좌표에서 일정 영역을 인식한다.

4. b 비트맵에서 해당 좌표 영역에 해당하는 픽셀 값(ARGB 값)을 가져온다.

5. a 비트맵의 해당 좌표 영역에 b 비트맵에서 가져온 픽셀 값을 설정한다.

6. 화면을 새로고친다.


일단 개념 설명은 위와 같이 간단하다. 그렇다면 실제 코드로 어떻게 구현 되는지 알아보자.



2. 코드로 구현

위의 개념을 실제 코드로 구현해 보자.


1. 2개의 비트맵을 가지고 있는다. (a, b)

int w = getWidth();                    //뷰의 가로 크기
int h = getHeight();                    //뷰의 세로 크기
       
Options opt = new Options();    //비트맵 생성 옵션
opt.inPurgeable = true;            //메모리 정리될 수 있게 설정


//지워질 그림에 대한 이미지 저장
Bitmap temp= BitmapFactory.decodeResource(res, drawable, opt);
currentBitmap = Bitmap.createScaledBitmap(temp, w, h, true);
       
//칠해질 그림에 대한 이미지 저장
temp= BitmapFactory.decodeResource(res, drawable, opt);
newBitmap = Bitmap.createScaledBitmap(temp, w, h, true);


2. a 비트맵을 먼저 그려서 보여준다

@Override
public void onDraw(Canvas canvas) {
    canvas.drawBitmap(currentBitmap, 0, 0, currentBitmapPaint);        //현재 비트맵을 그린다
}


3. 사용자의 터치한 곳의 좌표에서 일정 영역을 인식한다.

@Override
public boolean onTouchEvent(MotionEvent event) {

   if(event.getAction() == MotionEvent.ACTION_DOWN)
    return true;     //터치 다운이면 이벤트 계속 받게 true를 리턴
   else if(event.getAction() == MotionEvent.ACTION_MOVE) {
    scratchBitmap(x, y);            //터치한 곳의 비트맵의 픽셀값을 변경한다.
   }

   return super.onTouchEvent(event);
}


4. b 비트맵에서 해당 좌표 영역에 해당하는 픽셀 값(ARGB 값)을 가져온다.

5. a 비트맵의 해당 좌표 영역에 b 비트맵에서 가져온 픽셀 값을 설정한다.

6. 화면을 새로고친다.


private void scratchBitmap(float x, float y) {

    //새로운 비트맵의 픽셀 값을 가져온다
    newBitmap.getPixels(pixelArray, 0, radius, (int)x-radius/2, (int)y-radius/2, radius, radius);

    //현재 비트맵에 픽셀값을 설정한다
    currentBitmap.setPixels(pixelArray, 0, radius, (int)x-radius/2, (int)y-radius/2, radius, radius);
    invalidate();        //화면 새로 고침
}



3. 구현된 효과

여기서는 똑같은 이미지 2장을 이용한 처음에는 흑백 이미지를 보여주고 터치를 하여 지나가면 그 곳에는 컬러 이미지가 보여진다.






4. 성능 향상 팁

여기서는 리소스에서 이미지를 가져왔지만 비트맵을 sd카드에 있는 이미지나 서버에서 받아온 이미지로 생성할 수 있다.


또한 글로는 설명하지 않았지만 스크래치되는 영역을 둥글게 하는 라운드 처리도 해주었다.


여기까지는 제가 공개하는 것이고 이 다음 부터 성능 향상을 위해 튜닝하는 것을 이것을 사용하는 개발자의 몫이다.


팁을 드리자면 샘플코드에서는 터치 무브 이벤트가 들어올 때마다 비트맵을 새로 갱산한다.

이렇게 하는 것보다 일정 거리 이상 움직이거나 일정 갯수 이상의 이벤트가 오는 것을 모았다가 비트맵 갱신을 1번에 해주는 것이다.


또한 터치 좌표대로 갱신하면 빠르게 움직였을 경우 부자연스럽게 나올 수 있다. 이것을 보정하기 위해 터치 이벤트를 모아서 베지어 곡선을 만들어 해당 곡선 형태로 비트맵을 갱신하면 좀 더 자연스럽게 나온다.


전체 샘플 코드 첨부하였습니다.

*글과 자료는 출처만 밝히시면 얼마든지 가져다 쓰셔도 됩니다.


ScratchView.zip



ScratchView.zip
0.42MB