Android简单的圆盘形菜单

   今天偶然看到一个圆盘形的菜单,还可以转动,感觉挺有意思,然后想了想,做了个简单的效果。
      思路是这样的,定一个原点和一个半径,圆的四周均匀分布每个菜单。为了方便计算,菜单的坐标用度数表示,然后转化为极坐标计算。
      定某个点为起始点,根据总菜单数确定每个点增加的度数,然后依次确定每个点的度数,也就确定了坐标。

Java代码 复制代码 收藏代码
  1. package chroya.demo.roundspin; 
  2.  
  3. import android.content.Context; 
  4. import android.graphics.Bitmap; 
  5. import android.graphics.BitmapFactory; 
  6. import android.graphics.Canvas; 
  7. import android.graphics.Color; 
  8. import android.graphics.Paint; 
  9. import android.util.Log; 
  10. import android.view.MotionEvent; 
  11. import android.view.View; 
  12.  
  13. /**
  14. * 圆盘式的view
  15. * @author chroya
  16. *
  17. */ 
  18. public class RoundSpinView extends View { 
  19.     private Paint mPaint = new Paint(); 
  20.      
  21.     //stone列表 
  22.     private BigStone[] mStones; 
  23.     //数目 
  24.     private static final int STONE_COUNT = 6
  25.      
  26.     //圆心坐标 
  27.     private int mPointX=0, mPointY=0
  28.     //半径 
  29.     private int mRadius = 0
  30.     //每两个点间隔的角度 
  31.     private int mDegreeDelta; 
  32.  
  33.     public RoundSpinView(Context context, int px, int py, int radius) { 
  34.         super(context); 
  35.         mPaint.setColor(Color.RED); 
  36.         mPaint.setStrokeWidth(2); 
  37.         setBackgroundResource(R.drawable.menubkground); 
  38.          
  39.         mPointX = px; 
  40.         mPointY = py; 
  41.         mRadius = radius; 
  42.          
  43.         setupStones(); 
  44.         computeCoordinates(); 
  45.     } 
  46.      
  47.     /**
  48.      * 初始化每个点
  49.      */ 
  50.     private void setupStones() { 
  51.         mStones = new BigStone[STONE_COUNT]; 
  52.         BigStone stone; 
  53.         int angle = 0
  54.         mDegreeDelta = 360/STONE_COUNT; 
  55.          
  56.         for(int index=0; index<STONE_COUNT; index++) { 
  57.             stone = new BigStone(); 
  58.             stone.angle = angle; 
  59.             stone.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.menu1+index);             
  60.             angle += mDegreeDelta; 
  61.              
  62.             mStones[index] = stone; 
  63.         } 
  64.     } 
  65.      
  66.     /**
  67.      * 重新计算每个点的角度
  68.      */ 
  69.     private void resetStonesAngle(float x, float y) { 
  70.         int angle = computeCurrentAngle(x, y); 
  71.         Log.d("RoundSpinView", "angle:"+angle); 
  72.         for(int index=0; index<STONE_COUNT; index++) {            
  73.             mStones[index].angle = angle;        
  74.             angle += mDegreeDelta; 
  75.         } 
  76.     } 
  77.      
  78.     /**
  79.      * 计算每个点的坐标
  80.      */ 
  81.     private void computeCoordinates() { 
  82.         BigStone stone; 
  83.         for(int index=0; index<STONE_COUNT; index++) { 
  84.             stone = mStones[index]; 
  85.             stone.x = mPointX+ (float)(mRadius * Math.cos(stone.angle*Math.PI/180)); 
  86.             stone.y = mPointY+ (float)(mRadius * Math.sin(stone.angle*Math.PI/180)); 
  87.         } 
  88.     } 
  89.      
  90.     /**
  91.      * 计算第一个点的角度
  92.      * @param x
  93.      * @param y
  94.      * @return
  95.      */ 
  96.     private int computeCurrentAngle(float x, float y) {      
  97.         float distance = (float)Math.sqrt(((x-mPointX)*(x-mPointX) + (y-mPointY)*(y-mPointY))); 
  98.         int degree = (int)(Math.acos((x-mPointX)/distance)*180/Math.PI); 
  99.         if(y < mPointY) { 
  100.             degree = -degree; 
  101.         } 
  102.          
  103.         Log.d("RoundSpinView", "x:"+x+",y:"+y+",degree:"+degree); 
  104.         return degree; 
  105.     } 
  106.      
  107.     @Override 
  108.     public boolean dispatchTouchEvent(MotionEvent event) { 
  109.         resetStonesAngle(event.getX(), event.getY()); 
  110.         computeCoordinates(); 
  111.         invalidate(); 
  112.         return true
  113.     } 
  114.      
  115.     @Override 
  116.     public void onDraw(Canvas canvas) { 
  117.         canvas.drawPoint(mPointX, mPointY, mPaint); 
  118.          
  119.         for(int index=0; index<STONE_COUNT; index++) { 
  120.             if(!mStones[index].isVisible) continue
  121.             drawInCenter(canvas, mStones[index].bitmap, mStones[index].x, mStones[index].y); 
  122.             //不想有红线,就注掉下面这句 
  123. //          canvas.drawLine(mPointX, mPointY, mStones[index].x, mStones[index].y, mPaint); 
  124.         } 
  125.     } 
  126.      
  127.     /**
  128.      * 把中心点放到中心处
  129.      * @param canvas
  130.      * @param bitmap
  131.      * @param left
  132.      * @param top
  133.      */ 
  134.     void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) { 
  135.         canvas.drawPoint(left, top, mPaint); 
  136.         canvas.drawBitmap(bitmap, left-bitmap.getWidth()/2, top-bitmap.getHeight()/2, null); 
  137.     }    
  138.      
  139.     class BigStone { 
  140.          
  141.         //图片 
  142.         Bitmap bitmap; 
  143.          
  144.         //角度 
  145.         int angle; 
  146.          
  147.         //x坐标 
  148.         float x; 
  149.          
  150.         //y坐标 
  151.         float y; 
  152.          
  153.         //是否可见 
  154.         boolean isVisible = true
  155.     } 
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,代码也贡献出来。

 

zhuanzi:http://chroya.iteye.com/blog/830682

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值