public class Rocker extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(new RockerView(this)); } private class RockerView extends SurfaceView implements SurfaceHolder.Callback,Runnable{ private SurfaceHolder mSurfaceHolder; private Thread mThread; private Canvas mCanvas; private Paint mPaint; private boolean mIsFlag; private float mCircleX=100; private float mCircleY=100; private float mCircleR=50; private float mRockerCircleX=100; private float mRockerCircleY=100; private float mRockerCircleR=20; public RockerView(Context context) { super(context); mSurfaceHolder=this.getHolder(); mSurfaceHolder.addCallback(this); mPaint=new Paint(); mPaint.setAntiAlias(true); setFocusable(true); setFocusableInTouchMode(true); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { mIsFlag=true; mThread=new Thread(this); mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsFlag=false; } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN||event.getAction()==MotionEvent.ACTION_MOVE) { if (Math.sqrt((Math.pow(mCircleX-event.getX(), 2)+Math.pow(mCircleY-event.getY(), 2)))>mCircleR) { double angle=getAngle(mCircleX,mCircleY,event.getX(),event.getY()); setRockerXYInCircle(angle); }else { mRockerCircleX=event.getX(); mRockerCircleY=event.getY(); } return true; }else if (event.getAction()==MotionEvent.ACTION_UP) { mRockerCircleX=mCircleX; mRockerCircleY=mCircleY; return true; } return super.onTouchEvent(event); } private void setRockerXYInCircle(double angle) { mRockerCircleX=(float)(mCircleR*Math.cos(angle))+mCircleX; mRockerCircleY=(float)(mCircleR*Math.sin(angle))+mCircleY; } private double getAngle(float circleX, float circleY, float targetX, float targetY) { float disX=targetX-circleX; float disY=targetY-circleY; float hypotenuse=(float)Math.sqrt(Math.pow(disX, 2)+Math.pow(disY, 2)); float cosAngle=disX/hypotenuse; float angle=(float)Math.acos(cosAngle); if (targetY<circleY) { angle=-angle; } return angle; } @Override public void run() { while (mIsFlag) { doDraw(); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void doDraw() { try { mCanvas=mSurfaceHolder.lockCanvas(); if (mCanvas!=null) { mCanvas.drawColor(Color.WHITE); mPaint.setColor(0x70000000); mCanvas.drawCircle(mCircleX, mCircleY, mCircleR, mPaint); mPaint.setColor(0x70ff0000); mCanvas.drawCircle(mRockerCircleX, mRockerCircleY, mRockerCircleR, mPaint); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if (mCanvas!=null) { mSurfaceHolder.unlockCanvasAndPost(mCanvas); } } } } }
问题一:
@Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN||event.getAction()==MotionEvent.ACTION_MOVE) { if (Math.sqrt((Math.pow(mCircleX-event.getX(), 2)+Math.pow(mCircleY-event.getY(), 2)))>mCircleR) { double angle=getAngle(mCircleX,mCircleY,event.getX(),event.getY()); setRockerXYInCircle(angle); }else { mRockerCircleX=event.getX(); mRockerCircleY=event.getY(); } return true; }else if (event.getAction()==MotionEvent.ACTION_UP) { mRockerCircleX=mCircleX; mRockerCircleY=mCircleY; return true; } return super.onTouchEvent(event); }这个是当if (event.getAction()==MotionEvent.ACTION_DOWN||event.getAction()==MotionEvent.ACTION_MOVE) 当手指按下和移动的时候,计算摇杆的x和y坐标,当手指抬起的时候恢复和大圆相同的x和y坐标,再进行绘制的时候就会画在中间
问题二:
private void setRockerXYInCircle(double angle) { mRockerCircleX=(float)(mCircleR*Math.cos(angle))+mCircleX; mRockerCircleY=(float)(mCircleR*Math.sin(angle))+mCircleY; }当手指移动的距离大于大圆的半径的时候,要重新计算摇杆的x和y坐标,使其仍然在大圆的圆周上,也就是是大圆圆心和手指所在点的直线与圆周相交的点。
private double getAngle(float circleX, float circleY, float targetX, float targetY) { float disX=targetX-circleX; float disY=targetY-circleY; float hypotenuse=(float)Math.sqrt(Math.pow(disX, 2)+Math.pow(disY, 2)); float cosAngle=disX/hypotenuse; float angle=(float)Math.acos(cosAngle); if (targetY<circleY) { angle=-angle; } return angle; }这个还不是太理解,看来数学退化了。。。