이미지를 이용하여 움직이고 이벤트 발생하고 등을 구현합니다.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RatingBar;
public class MyView extends View{
int width,height; //화면의 폭과 높이
Bitmap back1,back2; //화면에 표시할 이미지
//버튼의 색 상태값을 정할 상수
final int NORMAL_STATE=0;
final int PUSH_STATE=1;
int state; //상태값을 저장할 변수
//버튼이 차지하고 있는 영역을 표시할 변수
int btn_minX,btn_maxX,btn_minY,btn_maxY;
//버튼이 차지하고 있는 영역을 표시할 사각형 객체
Rect rectBtn;
Bitmap pin; //바늘의 이미지
int pinW,pinH;//핀 이미지의 폭과 높이
float scaleRatioX,scaleRatioY; //이미지 확대축소 비율
int originalBackX,originalBackY; //원본배경이미지의 크기
int originalPinX,originalPinY; //원본 핀의 크기
int dialX,dialY;//핀을 위치시킬 좌표
int angle; //캔바스의 현재 돌아간 각도
int angleSpeed=10;//캔바스의를 돌리는 각속도
//생성자
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
//화면에 표시할 이미지를 읽어온다.
back1=BitmapFactory.decodeResource(getResources(),
R.drawable.back1);
back2=BitmapFactory.decodeResource(getResources(),
R.drawable.back2);
pin=BitmapFactory.decodeResource(getResources(),
R.drawable.pin);
//핸들러를 호출해서 화면이 지속적으로 갱신되도록한다.
handler.sendEmptyMessage(0);
//원본 배경이미지의 크기 구하기
originalBackX=back1.getWidth(); //이미지의 폭
originalBackY=back1.getHeight(); //이미지의 높이
//원본 핀 이미지의 크기 구하기
originalPinX=pin.getWidth();
originalPinY=pin.getHeight();
}
//
// [[ onDraw()메소드 ]]
//
// - 화면을 처음 구성할때 한번 호출되어서 화면에 무언가를 그린다.
// - invalidate() 메소드를 호출하면 화면이 무효화 되고 다시 그리기
// 위해서 다시 한번 호출된다.
//
public void onDraw(Canvas canvas){
//현재 상태에 따라서 다른 이미지를 그린다.
switch(state){
case NORMAL_STATE: //누르지 않은 상태 일때
//이미지를 화면에 그린다
canvas.drawBitmap(back1, 0, 0, null);
break;
case PUSH_STATE: //누르고 있는 상태 일때
//이미지를 화면에 그린다
canvas.drawBitmap(back2, 0, 0, null);
break;
}
//캔바스 회전 시키기
canvas.rotate(angle, dialX, dialY);
canvas.drawBitmap(pin, dialX-pinW/2 ,//핀의 x 좌표
dialY-pinH+(int)(pinH/4.8), //핀의 y 좌표
null);
}
//캔바스 회전 시키는 메소드
public void rotateCanvas(){
angle += angleSpeed ; //각속도 만큼 캔바스를 회전 시킨다
if( angle >= 90 || angle <= -90)
angleSpeed *= -1 ; //부호를 바꾸어서 반대로 회전하게한다.
}
//View 가 실제로 차지하고 있는 크기에 대한 정보가 들어온다.
protected void onSizeChanged
(int w, int h, int oldw, int oldh) {
//화면의 폭과 높이 필드에 저장하기
width = w;
height = h;
Log.e("#####","onSizeChanged()");
//이미지 축소 비율구하기
scaleRatioX = w / (originalBackX * 1.0f) ;
scaleRatioY = h / (originalBackY * 1.0f) ;
//화면의 크기에 맞게 이미지의 크기를 스케일하기
back1=Bitmap.createScaledBitmap(back1, w, h, false);
back2=Bitmap.createScaledBitmap(back2, w, h, false);
//배경이 줄어든만큼 바늘의 크기도 같은 비율로 줄이기
pinW = (int)(originalPinX * scaleRatioX);
pinH = (int)(originalPinY * scaleRatioY);
pin = Bitmap.createScaledBitmap(pin, pinW, pinH, false);
btn_minX=w/3;
btn_maxX=2*w/3;
btn_minY=h-h/10;
btn_maxY=h;
//사각형 객체 생성하기
rectBtn=new Rect(btn_minX,btn_minY,btn_maxX,btn_maxY);
//핀을 위치 시킬 좌표 구하기
dialX = w / 2;
dialY = ( h / 3) * 2;
};
//터치 입력을 받기 위해서
public boolean onTouchEvent(MotionEvent event) {
//터치한 곳의 좌표를 읽어오기.
int touchedX=(int)event.getX();
int touchedY=(int)event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: //액션 다운 이벤트가 발생했을때
/*
if(touchedX > btn_minX && touchedX < btn_maxX &&
touchedY > btn_minY && touchedY < btn_maxY){
state=PUSH_STATE; //상태값을 바꿔준다.
}
*/
//Rect객체를 이용한다면
if(rectBtn.contains(touchedX, touchedY)){
state=PUSH_STATE; //상태값을 바꿔준다.
}
break;
case MotionEvent.ACTION_UP: //액션 업 이벤트가 일어났을때
state=NORMAL_STATE;
break;
}
return true; //ACTION_MOVE, ACTION_UP 이벤트도 받기 위해서
};
//지속적인 화면 갱신을 위해서 핸들러에서 화면을 무한루프 돌면서 갱신하게 한다.
Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
//화면 갱신한다.
invalidate();
if(state != PUSH_STATE){ //버튼을 누르고 있는 상태가 아닐때
//핀을 움직이게 하기 위해서
rotateCanvas();
}
// 10 / 1000 초마다 자신의 객체를 재귀호출한다.(무한루프)
handler.sendEmptyMessageDelayed(0, 10);
}
};
}