Android 实现指南针效果

Android 实现指南针效果

前一段时间在做指南针,于是想偷偷懒.在网上直接找一个Demo.然后改改旧差不多了.可是看到的效果却和预期的差太多了,所以就不得不自己撸一个:

大致上会用到内容

  • 自定义View
  • GPS定位模块
  • 方向传感器

开始,创建一个view

  • 先写一个类继承view
  • 不断对OnDraw事件进行重绘
  • 传入方向

OK.那么新建一个DirectionView 来继承view

public class DirectionView extends View {
    
}

那么绘制需要用到什么。用到画笔。宽度。等等一系列参数。

public class DirectionView extends View {

   /**
    * 圆环使用
    * */
   private Paint mRingPaint;

   private Paint mCententPaint; //绘制中心实线的画布

   /**
    * 圆环半径 根据view的宽度计算
    * */
   private int mRadius = 200;

   /**
    * 圆环的中心点 -- 画圆环和旋转画布时需要使用
    * */
   private int x, y;

   /**
    * 圆环动画使用 -- 与mRingPaint唯一不同得方在于颜色
    * */
   private Paint mRingAnimPaint;

   /**
    * 圆环大小 矩形
    * */
   private RectF mRectf;

   private Context mContext;

   /**
    * 圆环 宽度
    * */
   private final int mHeartPaintWidth = 50;

   /**
    * 圆环动画开始时 画弧的偏移量
    * */
   private int mAnimAngle = -1;
   }

初始化部分我们先不管。看到效果图.我们是不是需要先将360度的齿轮画好。
这里我们就需要对ondraw 来操作了。
绘制嘛。必须要画板嘛

	canvas.setDrawFilter(mDrawFilter);//在canvas上抗锯齿
        //由于drawArc默认从x轴开始画,因此需要将画布旋转或者绘制角度旋转,2种方案
        //int level = canvas.save();
        //先绘制竖线
        canvas.drawLine(x,mRectf.top + 30, x  , mRectf.top - 60,mCententPaint);
        //绘制中心线
        canvas.drawLine(x,y-80,x,y + 80,mCententPaint);

        canvas.drawLine(x - 80,y,x + 80, y ,mCententPaint);
        canvas.rotate(rotate, x, y);// 旋转的时候一定要指明中心

        for (int i = 0; i < 360; i += 3) {
            canvas.drawArc(mRectf, i, 1, false, mRingPaint);
        }

这里喔们把360度的齿轮绘制了。大致上是每隔3度绘制一条。
那么绘制齿轮之后。我们是不是需要绘制东西南北了。

mCententPaint.setTextSize(50);
        mCententPaint.setColor(Color.RED);
        canvas.drawText("北",x,mRectf.top + mHeartPaintWidth  + 50,mCententPaint);
        mCententPaint.setColor(Color.BLACK);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("东",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("南",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("西",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        mCententPaint.setTextSize(30);
        for (int i = 0; i < 360; i += 3) {
            if(i == 0|| i == 30 || i ==60 || i ==90 || i ==120 || i == 150 || i == 180 || i == 210 || i == 240 || i == 270 || i == 300 || i == 330 || i== 0){
                canvas.drawText(""+i,x,mRectf.top - mHeartPaintWidth ,mCententPaint);
                canvas.rotate(30, x, y);// 旋转的时候一定要指明中心
            }
        }

那么整个代码就是:

package com.jonkming.easyui.hardware.compass.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DrawFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.jonkming.easyui.R;

/**
 * 指南针的自定位View
* @Title: DirectionView.java
* @Package com.jonkming.easyui.hardware.compass.ui
* @author HuangMingming
* @date 2016/11/10 19:16
* @version V1.0
*/
public class DirectionView extends View {

    /**
     * 圆环使用
     * */
    private Paint mRingPaint;

    private Paint mCententPaint; //绘制中心实线的画布

    /**
     * 圆环半径 根据view的宽度计算
     * */
    private int mRadius = 200;

    /**
     * 圆环的中心点 -- 画圆环和旋转画布时需要使用
     * */
    private int x, y;

    /**
     * 圆环动画使用 -- 与mRingPaint唯一不同得方在于颜色
     * */
    private Paint mRingAnimPaint;

    /**
     * 圆环大小 矩形
     * */
    private RectF mRectf;

    private Context mContext;

    /**
     * 圆环 宽度
     * */
    private final int mHeartPaintWidth = 50;

    /**
     * 圆环动画开始时 画弧的偏移量
     * */
    private int mAnimAngle = -1;

    public DirectionView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);

        this.mContext = context;
        init();
    }

    public DirectionView(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
        this.mContext = context;
        init();
    }

    public DirectionView(Context context)
    {
        this(context, null);
        this.mContext = context;
        init();
    }

    private  void init(){
        mRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRingPaint.setStrokeWidth(mHeartPaintWidth);
        mRingPaint.setStyle(Paint.Style.STROKE);
        mRingAnimPaint = new Paint(mRingPaint);
        mRingAnimPaint.setColor(Color.WHITE);
        //初始化心跳曲线
        mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);

        mCententPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mCententPaint.setColor(Color.BLACK);

        mCententPaint.setStrokeWidth(3);
    }
    /**
     * canvas抗锯齿开启需要
     * */
    private DrawFilter mDrawFilter;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        x = w / 2;
        y = h / 2;
        mRadius = w / 2 - mHeartPaintWidth * 3; //因为制定了Paint的宽度,因此计算半径需要减去这个
        mRectf = new RectF(x - mRadius, y - mRadius, x + mRadius, y + mRadius);
    }
    public float rotate = 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.setDrawFilter(mDrawFilter);//在canvas上抗锯齿
        //由于drawArc默认从x轴开始画,因此需要将画布旋转或者绘制角度旋转,2种方案
        //int level = canvas.save();
        //先绘制竖线
        canvas.drawLine(x,mRectf.top + 30, x  , mRectf.top - 60,mCententPaint);
        //绘制中心线
        canvas.drawLine(x,y-80,x,y + 80,mCententPaint);

        canvas.drawLine(x - 80,y,x + 80, y ,mCententPaint);
        canvas.rotate(rotate, x, y);// 旋转的时候一定要指明中心

        for (int i = 0; i < 360; i += 3) {
            canvas.drawArc(mRectf, i, 1, false, mRingPaint);
        }
        mCententPaint.setTextSize(50);
        mCententPaint.setColor(Color.RED);
        canvas.drawText("北",x,mRectf.top + mHeartPaintWidth  + 50,mCententPaint);
        mCententPaint.setColor(Color.BLACK);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("东",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("南",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        canvas.drawText("西",x,mRectf.top + mHeartPaintWidth + 50,mCententPaint);
        canvas.rotate(90, x, y);// 旋转的时候一定要指明中心
        mCententPaint.setTextSize(30);
        for (int i = 0; i < 360; i += 3) {
            if(i == 0|| i == 30 || i ==60 || i ==90 || i ==120 || i == 150 || i == 180 || i == 210 || i == 240 || i == 270 || i == 300 || i == 330 || i== 0){
                canvas.drawText(""+i,x,mRectf.top - mHeartPaintWidth ,mCententPaint);
                canvas.rotate(30, x, y);// 旋转的时候一定要指明中心
            }
        }
    }
}

绘制完了之后我们是不是要写界面代码了。这里xml 布局就不贴出来了。后面可以直接去github 去看看
主界面主要的作用就是对sensor监听。并返回方向的角度。然后对上面定义的view进行方向赋值。然后通知view 重绘就可以了

	@Override
    protected void onResume() {
        /**
         *  获取方向传感器
         *  通过SensorManager对象获取相应的Sensor类型的对象
         */
        Sensor sensor = manager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        //应用在前台时候注册监听器
        manager.registerListener(listener, sensor,
                SensorManager.SENSOR_DELAY_GAME);
        super.onResume();
    }

    @Override
    protected void onPause() {
        //应用不在前台时候销毁掉监听器
        manager.unregisterListener(listener);
        super.onPause();
    }

    private final class SensorListener implements SensorEventListener {

        private float predegree = 0;

        @Override
        public void onSensorChanged(SensorEvent event) {
            /**
             *  values[0]: x-axis 方向加速度
                values[1]: y-axis 方向加速度
               values[2]: z-axis 方向加速度
             */
            float degree = event.values[0];// 存放了方向值
            predegree=-degree;
            mCompassDegreeTxt.setText(""+((int)degree)+"°");
            mCompassDirectionTxt.setText(formatPredegree(degree));
            directionView.rotate = predegree;

            directionView.postInvalidate();
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }

    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值