当前位置: 代码迷 >> Android >> Android容易的圆盘形菜单
  详细解决方案

Android容易的圆盘形菜单

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

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个菜单的效果,画了线的:


   
  相关解决方案