일단 맵을 크게 그려놓고, 그 안에서 스크롤도 하고
특정 영역을 클릭하면 반응하게 하는 화면을 쉽게 볼 수 있었을 것이다.
이는 SurfaceView를 통해 구현이 가능하다.
SurfaceView의 Thread관리에 대해서는 이전에 포스팅한게 있으니
그것을 참고하여 죽지 않는 SurfaceView를 구현하시길 바랍니다.
일단 큰 이미지를 준비해주세요
예를 들어, 휴대폰 해상도가 1280 * 704 라고 하면
이미지의 사이즈가 1500 * 1000 정도는 되어야 스크롤을 할 껀덕지가 생깁니다.
1. 화면 스크롤 구현
전역 변수로 다음 변수를 두고
int cur_x = 0;
int cur_y = 0;
화면 터치해서 움직임이 있는 만큼, cur_x, cur_y를 움직여 줍니다.
화면을 터치해서 오른쪽으로 20만큼 움직이는 행동을 했으면
cur_x를 + 20 해줍니다.
그리고, 배경 이미지를 그려주는 쪽에서는
canvas.drawBitmap(backImg,
new Rect(cur_x, cur_y, cur_x+screenWidth,cur_y+screenHeight),
new Rect(0, 0, screenWidth, screenHeight),
null);
이것의 의미가 뭐냐면, 2번째 인자로 넘겨준 Rect는
이미지 원본 크기에서 그려줄 영역을 지정하는 것입니다.
즉, 우리가 1500 * 1000 의 이미지를 준비했다면,
이 이미지의 2번째 인자의 Rect 에 해당하는 영역을 crop(잘라내기) 해서
3번쨰 인자로 넘겨준 화면의 크기에 그리겠다는 의미가 된다.
다시 한번 정리하자면,
이미지 원본 크기 (1500 * 1000)
2번쨰 인자의 Rect : 이미지 원본 크기에서 잘라낼 영역
3번째 인자의 Rect : 잘라낸 이미지를 그릴 스마트폰 화면상의 영역
따라서, 2번째 인자의 Rect가 크기가
3번쨰 인자의 Rect보다 작으면
그만큼 확대가 되어서 보이게 됩니다. (화질이 떨어지겠죠)
20*20 의 사이즈의 이미지를 40 * 40 에 그리라고 하면 2배로 확대가 됩니다.
20*20 의 사이즈의 이미지를 40 * 40 에 그리라고 하면 2배로 확대가 됩니다.
2. 특정 영역을 버튼으로 지정하기
먼저 버튼으로 지정하고 싶은 특정 영역을 Rect로 지정합니다.
Rect clickRect = new Rect(500, 500, 650, 650);
여기서의 Rect의 좌표는 원본 이미지에서의 위치입니다.
Rect clickRect = new Rect(500, 500, 650, 650);
여기서의 Rect의 좌표는 원본 이미지에서의 위치입니다.
그리고, 같은 값으로 Rect를 하나 더 만듭니다.
Rect newRect = new Rect(500, 500, 650, 650);
이 newRect는 화면의 스크롤에 따라서 값이 바뀌어야 합니다.
newRect.set(clickRect.left - cur_x, clickRect.top - cur_y, clickRect.right - cur_x, clickRect.bottom - cur_y);
화면의 스크롤에 따라서 버튼 영역이 상대적으로 계산이 되게 됩니다
그럼, onTouchEvent 에서는 newRect의 영역안에 터치한 좌표가 들어가는지
체크하여 반응시키면 됩니다. Rect클래스에 contains(x,y)라는 함수가 있으니
활용하면 됩니다.
활용하면 됩니다.
코드
int past_x = 0; int past_y = 0; int cur_x = 0; int cur_y = 0; Rect clickRect = new Rect(500, 500, 650, 650); Rect newRect = new Rect(500, 500, 650, 650); @Override public boolean onTouchEvent(MotionEvent event) { int keyAction = event.getAction(); int x = (int)event.getX(); int y = (int)event.getY(); switch (keyAction){ case MotionEvent.ACTION_DOWN: past_x = x; past_y = y; break; case MotionEvent.ACTION_MOVE: cur_x = cur_x + (past_x - x ); cur_y = cur_y + (past_y - y); if (cur_x <0) cur_x = 0; if (cur_x > screenWidth) cur_x = screenWidth; if (cur_y <0) cur_y = 0; if (cur_y > screenHeight) cur_y = screenHeight; past_x = x; past_y = y; break; } return true; } boolean first = true; @Override public void run() { Canvas canvas; while (isItOk) { canvas = holder.lockCanvas(); if (first) { screenWidth = canvas.getWidth(); screenHeight = canvas.getHeight(); first = false; } //배경 이미지의 크기 int width = worldmap.getWidth(); int height = worldmap.getHeight(); canvas.drawBitmap(worldmap, new Rect(cur_x, cur_y, cur_x+screenWidth,cur_y+screenHeight), new Rect(0, 0, screenWidth * 1, screenHeight * 1), null); canvas.drawText("screen " +screenWidth + "," + screenHeight + " image " + width + " " + height, 0, 50, p); newRect.set(clickRect.left - cur_x, clickRect.top - cur_y, clickRect.right - cur_x, clickRect.bottom - cur_y); canvas.drawRect(newRect, p); holder.unlockCanvasAndPost(canvas); } }
댓글 없음:
댓글 쓰기