Android簡單的圓盤形菜單 博客分類: Android Android360

   今天偶然看到一個圓盤形的菜單,還可以轉動,感覺挺有意思,然後想了想,做了個簡單的效果。       思路是這樣的,定一個原點和一個半徑,圓的四周均勻分佈每個菜單。爲了方便計算,菜單的座標用度數表示,然後轉化爲極座標計算。       定某個點爲起始點,根據總菜單數確定每個點增加的度數,然後依次確定每個點的度數,也就確定了座標。

package chroya.demo.roundspin;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * 圓盤式的view
 * @author chroya
 *
 */
public class RoundSpinView extends View {
	private Paint mPaint = new Paint();
	
	//stone列表
	private BigStone[] mStones;
	//數目
	private static final int STONE_COUNT = 6;
	
	//圓心座標
	private int mPointX=0, mPointY=0;
	//半徑
	private int mRadius = 0;
	//每兩個點間隔的角度
	private int mDegreeDelta;

	public RoundSpinView(Context context, int px, int py, int radius) {
		super(context);
		mPaint.setColor(Color.RED);
		mPaint.setStrokeWidth(2);
		setBackgroundResource(R.drawable.menubkground);
		
		mPointX = px;
		mPointY = py;
		mRadius = radius;
		
		setupStones();
		computeCoordinates();
	}
	
	/**
	 * 初始化每個點
	 */
	private void setupStones() {
		mStones = new BigStone[STONE_COUNT];
		BigStone stone;
		int angle = 0;
		mDegreeDelta = 360/STONE_COUNT;
		
		for(int index=0; index<STONE_COUNT; index++) {
			stone = new BigStone();
			stone.angle = angle;
			stone.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.menu1+index);			
			angle += mDegreeDelta;
			
			mStones[index] = stone;
		}
	}
	
	/**
	 * 重新計算每個點的角度
	 */
	private void resetStonesAngle(float x, float y) {
		int angle = computeCurrentAngle(x, y);
		Log.d("RoundSpinView", "angle:"+angle);
		for(int index=0; index<STONE_COUNT; index++) {			
			mStones[index].angle = angle;		
			angle += mDegreeDelta;
		}
	}
	
	/**
	 * 計算每個點的座標
	 */
	private void computeCoordinates() {
		BigStone stone;
		for(int index=0; index<STONE_COUNT; index++) {
			stone = mStones[index];
			stone.x = mPointX+ (float)(mRadius * Math.cos(stone.angle*Math.PI/180));
			stone.y = mPointY+ (float)(mRadius * Math.sin(stone.angle*Math.PI/180));
		}
	}
	
	/**
	 * 計算第一個點的角度
	 * @param x
	 * @param y
	 * @return
	 */
	private int computeCurrentAngle(float x, float y) {		
		float distance = (float)Math.sqrt(((x-mPointX)*(x-mPointX) + (y-mPointY)*(y-mPointY)));
		int degree = (int)(Math.acos((x-mPointX)/distance)*180/Math.PI);
		if(y < mPointY) {
			degree = -degree;
		}
		
		Log.d("RoundSpinView", "x:"+x+",y:"+y+",degree:"+degree);
		return degree;
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		resetStonesAngle(event.getX(), event.getY());
		computeCoordinates();
		invalidate();
		return true;
	}
	
	@Override
	public void onDraw(Canvas canvas) {
		canvas.drawPoint(mPointX, mPointY, mPaint);
		
		for(int index=0; index<STONE_COUNT; index++) {
			if(!mStones[index].isVisible) continue;
			drawInCenter(canvas, mStones[index].bitmap, mStones[index].x, mStones[index].y);
			//不想有紅線,就注掉下面這句
//			canvas.drawLine(mPointX, mPointY, mStones[index].x, mStones[index].y, mPaint);
		}
	}
	
	/**
	 * 把中心點放到中心處
	 * @param canvas
	 * @param bitmap
	 * @param left
	 * @param top
	 */
	void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {
		canvas.drawPoint(left, top, mPaint);
		canvas.drawBitmap(bitmap, left-bitmap.getWidth()/2, top-bitmap.getHeight()/2, null);
	}	
	
	class BigStone {
		
		//圖片
		Bitmap bitmap;
		
		//角度
		int angle;
		
		//x座標
		float x;
		
		//y座標
		float y;
		
		//是否可見
		boolean isVisible = true;
	}
}

       代碼裏註釋也很清楚。STONE_COUNT表示菜單的數目,可以設置爲1到7,更大的數字需要圖片支持,我只放了7張圖片。

       如果觸摸的點不在圓周上,會自動計算出點到圓心的直線跟圓的交點,然後映射上去。

       5個菜單的效果,畫了線的:

       6個菜單的效果:

          Ok,代碼也貢獻出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章