이미지를 이용하여 움직이고 이벤트 발생하고 등을 구현합니다.

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);
			
		}
	};
	
}

posted by 쪼재