水平仪控件

public class LevelViewextends View {

/**

* 最大圈半径

*/

    private float mLimitRadius =0;

    boolean isoverDraw =true;

    /**

* 气泡半径

*/

    private float mBubbleRadius;

    /**

* 最大限制圈颜色

*/

    private int mLimitColor;

    /**

* 限制圈宽度

*/

    private float mLimitCircleWidth;

    /**

* 气泡中心标准圆颜色

*/

    private int mBubbleRuleColor;

    /**

* 气泡中心标准圆宽

*/

    private float mBubbleRuleWidth;

    /**

* 气泡中心标准圆半径

*/

    private float mBubbleRuleRadius;

    /**

* 水平后的颜色

*/

    private int mHorizontalColor;

    /**

* 气泡颜色

*/

    private int mBubbleColor;

    private PaintmBubblePaint;

    private PaintmLimitPaint;

    private PaintmBubbleRulePaint;

    /**

* 中心点坐标

*/

    private PointFcenterPnt =new PointF();

    /**

* 计算后的气泡点

*/

    private PointFbubblePoint;

    private double pitchAngle =0;

    private double rollAngle =0;

    private double doubley;

    private double doublex;

    private Vibratorvibrator;

    Handlerhandler =new Handler() {

@Override

        public void handleMessage(Message msg) {

//考虑气泡边界不超出限制圆,此处减去气泡的显示半径,做为最终的限制圆半径

            float limitRadius =mLimitRadius -mBubbleRadius;

            bubblePoint = convertCoordinate(rollAngle, pitchAngle, mLimitRadius);

            outLimit(bubblePoint, limitRadius);

            //坐标超出最大圆,取法向圆上的点

            if (outLimit(bubblePoint, limitRadius)) {

onCirclePoint(bubblePoint, limitRadius);

            }

invalidate();

            handler.sendEmptyMessageDelayed(1000, 5);

                if (doubley >rollAngle&&doubley-rollAngle>0.03) {

rollAngle +=0.01;

                }else if (doubley

rollAngle -=0.01;

                }

if (doublex >pitchAngle&&doublex-pitchAngle>0.03) {

pitchAngle +=0.01;

                }else if (doublex

pitchAngle -=0.01;

                }

}

};

    public LevelView(Context context) {

super(context);

        init(null, 0);

    }

public LevelView(Context context, AttributeSet attrs) {

super(context, attrs);

        init(attrs, 0);

    }

public LevelView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

        init(attrs, defStyle);

    }

private void init(AttributeSet attrs, int defStyle) {

// Load attributes

        handler.sendEmptyMessageDelayed(1000, 50);

        final TypedArray a = getContext().obtainStyledAttributes(

attrs, R.styleable.LevelView, defStyle, 0);

        mBubbleRuleColor = a.getColor(R.styleable.LevelView_bubbleRuleColor, mBubbleRuleColor);

        mBubbleColor = a.getColor(R.styleable.LevelView_bubbleColor, mBubbleColor);

        mLimitColor = a.getColor(R.styleable.LevelView_limitColor, mLimitColor);

        mHorizontalColor = a.getColor(R.styleable.LevelView_horizontalColor, mHorizontalColor);

        mLimitRadius = a.getDimension(R.styleable.LevelView_limitRadius, mLimitRadius);

        mBubbleRadius = a.getDimension(R.styleable.LevelView_bubbleRadius, mBubbleRadius);

        mLimitCircleWidth = a.getDimension(R.styleable.LevelView_limitCircleWidth, mLimitCircleWidth);

        mBubbleRuleWidth = a.getDimension(R.styleable.LevelView_bubbleRuleWidth, mBubbleRuleWidth);

        mBubbleRuleRadius = a.getDimension(R.styleable.LevelView_bubbleRuleRadius, mBubbleRuleRadius);

        a.recycle();

        mBubblePaint =new Paint();

        mBubblePaint.setColor(mBubbleColor);

        mBubblePaint.setStyle(Paint.Style.STROKE);

        mBubblePaint.setAntiAlias(true);

        mLimitPaint =new Paint();

        mLimitPaint.setStyle(Paint.Style.STROKE);

        mLimitPaint.setColor(mLimitColor);

        mLimitPaint.setStrokeWidth(mLimitCircleWidth);

        //抗锯齿

        mLimitPaint.setAntiAlias(true);

        mBubbleRulePaint =new Paint();

        mBubbleRulePaint.setColor(mBubbleRuleColor);

        mBubbleRulePaint.setStyle(Paint.Style.FILL);

        mBubbleRulePaint.setStrokeWidth(mBubbleRuleWidth);

        mBubbleRulePaint.setAntiAlias(true);

        vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);

    }

@Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        calculateCenter(widthMeasureSpec, heightMeasureSpec);

    }

private void calculateCenter(int widthMeasureSpec, int heightMeasureSpec) {

int width = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.UNSPECIFIED);

        int height = MeasureSpec.makeMeasureSpec(heightMeasureSpec, MeasureSpec.UNSPECIFIED);

        int center = Math.min(width, height) /2;

        centerPnt.set(center, center);

    }

@Override

    protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

        boolean isCenter = isCenter(bubblePoint);

        int limitCircleColor = isCenter ?mHorizontalColor :mLimitColor;

        int bubbleColor = isCenter ?mHorizontalColor :mBubbleColor;

        if (this.isCenter !=null) {

this.isCenter.isCenter(isCenter);

        }

mBubblePaint.setColor(bubbleColor);

        mLimitPaint.setColor(limitCircleColor);

        mBubbleRulePaint.setColor(bubbleColor);

        canvas.drawCircle(centerPnt.x, centerPnt.y, mBubbleRuleRadius, mBubbleRulePaint);

        canvas.drawCircle(centerPnt.x, centerPnt.y, mLimitRadius, mLimitPaint);

        drawBubble(canvas);

    }

private boolean isCenter(PointF bubblePoint) {

if (bubblePoint ==null) {

return false;

        }

return Math.abs(bubblePoint.x -centerPnt.x) <20 && Math.abs(bubblePoint.y -centerPnt.y) <20;

    }

private void drawBubble(Canvas canvas) {

if (bubblePoint !=null) {

canvas.drawCircle(bubblePoint.x, bubblePoint.y, mBubbleRadius, mBubblePaint);

        }

}

/**

* Convert angle to screen coordinate point.

*

    * @param rollAngle  横滚角(弧度)

    * @param pitchAngle 俯仰角(弧度)

    * @return

    */

    private PointFconvertCoordinate(double rollAngle, double pitchAngle, double radius) {

double scale = radius / Math.toRadians(90);

        //以圆心为原点,使用弧度表示坐标

        double x0 = -(rollAngle * scale);

        double y0 = -(pitchAngle * scale);

        //使用屏幕坐标表示气泡点

        double x =centerPnt.x - x0;

        double y =centerPnt.y - y0;

        return new PointF((float) x, (float) y);

    }

/**

    * @param rollAngle  (弧度)

*/

    public void setAngle(double rollAngle) {

this.doubley = rollAngle;

    }

public void  setpitchAngle(double pitchAngle){

this.doublex = pitchAngle;

    }

/**

    * 验证气泡点是否超过限制{@link #mLimitRadius}

*

    * @param bubblePnt

    * @return

    */

    private boolean outLimit(PointF bubblePnt, float limitRadius) {

float cSqrt = (bubblePnt.x -centerPnt.x) * (bubblePnt.x -centerPnt.x)

+ (centerPnt.y - bubblePnt.y) * +(centerPnt.y - bubblePnt.y);

        return cSqrt - limitRadius * limitRadius >0;

    }

/**

* 计算圆心到 bubblePnt点在圆上的交点坐标

* 即超出圆后的最大圆上坐标

*

    * @param bubblePnt  气泡点

    * @param limitRadius 限制圆的半径

    * @return

    */

    private PointFonCirclePoint(PointF bubblePnt, double limitRadius) {

double azimuth = Math.atan2((bubblePnt.y -centerPnt.y), (bubblePnt.x -centerPnt.x));

        azimuth = azimuth <0 ?2 * Math.PI + azimuth : azimuth;

        //圆心+半径+角度 求圆上的坐标

        double x1 =centerPnt.x + limitRadius * Math.cos(azimuth);

        double y1 =centerPnt.y + limitRadius * Math.sin(azimuth);

        bubblePnt.set((float) x1, (float) y1);

        return bubblePnt;

    }

public double getPitchAngle() {

return this.pitchAngle;

    }

public double getRollAngle() {

return this.rollAngle;

    }

OnViewIsCenterisCenter;

    public void setOnViewIsCenter(OnViewIsCenter isCenter) {

this.isCenter = isCenter;

    }

public interface OnViewIsCenter {

void isCenter(boolean iscenter);

    }

}

你可能感兴趣的:(水平仪控件)