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;
}这个还不是太理解,看来数学退化了。。。