水平儀控件

public class LevelViewextends View {

/**

* 最大圈半徑

*/

? ? private float mLimitRadius =0;

? ? boolean isoverDraw =true;

? ? /**

* 氣泡半徑

*/

? ? private float mBubbleRadius;

? ? /**

* 最大限制圈顏色

*/

? ? private int mLimitColor;

? ? /**

* 限制圈寬度

*/

? ? private float mLimitCircleWidth;

? ? /**

* 氣泡中心標(biāo)準(zhǔn)圓顏色

*/

? ? private int mBubbleRuleColor;

? ? /**

* 氣泡中心標(biāo)準(zhǔn)圓寬

*/

? ? private float mBubbleRuleWidth;

? ? /**

* 氣泡中心標(biāo)準(zhǔn)圓半徑

*/

? ? private float mBubbleRuleRadius;

? ? /**

* 水平后的顏色

*/

? ? private int mHorizontalColor;

? ? /**

* 氣泡顏色

*/

? ? private int mBubbleColor;

? ? private PaintmBubblePaint;

? ? private PaintmLimitPaint;

? ? private PaintmBubbleRulePaint;

? ? /**

* 中心點(diǎn)坐標(biāo)

*/

? ? private PointFcenterPnt =new PointF();

? ? /**

* 計(jì)算后的氣泡點(diǎn)

*/

? ? 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);

? ? ? ? ? ? //坐標(biāo)超出最大圓,取法向圓上的點(diǎn)

? ? ? ? ? ? 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);

? ? ? ? //以圓心為原點(diǎn),使用弧度表示坐標(biāo)

? ? ? ? double x0 = -(rollAngle * scale);

? ? ? ? double y0 = -(pitchAngle * scale);

? ? ? ? //使用屏幕坐標(biāo)表示氣泡點(diǎn)

? ? ? ? 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;

? ? }

/**

? ? * 驗(yàn)證氣泡點(diǎn)是否超過限制{@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;

? ? }

/**

* 計(jì)算圓心到 bubblePnt點(diǎn)在圓上的交點(diǎn)坐標(biāo)

* 即超出圓后的最大圓上坐標(biāo)

*

? ? * @param bubblePnt? 氣泡點(diǎn)

? ? * @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;

? ? ? ? //圓心+半徑+角度 求圓上的坐標(biāo)

? ? ? ? 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);

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容