Android 画出来的指南针

自从写完那个自定义菊花加载view后,又想着来一个类似的,这种知识点可以用在很多地方,如果手表,水表、还有今天要说的指南针等,只要是带刻度的都可以。
首先我们考虑下这个指南针要包括什么:
1、方位角刻度:也就是我当前位置和目的位置的方位角,方位角是与北方向相比偏离的角度。
2、东南西北不同颜色区分
3、根据手的水平移动,指南针view也要对应移动

获取指南针角度,可用SensorManager,这个是个系统服务,即可实时获取当前指向角度了。注册代码:

if(sensorManager==null){
            sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
            //通过 getDefaultSensor 获得指南针传感器
            sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
            //为传感器管理者注册监听器,第三个参数指获取速度正常
            sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}

这里我注册的是SENSOR_DELAY_GAME,游戏级别的传感器,之前我用的是SENSOR_DELAY_NORMAL默认的,感觉没游戏级别的好。
画刻度还是老样子,for循环360度,每一度画一个刻度,画完后将canvas旋转一度

for (int i = 0; i < 360; i++) {
            canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.2), mPaint);
            canvas.rotate(360 / 360, x, y);
}

至于其他特别的刻度比如红色刻度、长一些的刻度,我们可以做判断也可以另起for循环画,达到覆盖他的效果。话不多说直接上源码:

public class DemoZhiNaZhen extends View implements SensorEventListener {

    private int mWidth;
    private int mHeigth;
    private Sensor sensor;
    private SensorManager sensorManager;
    private int toDegrees;
    private Paint mPaint;

    public void setCureentAngla(int mCureentAngla) {
        this.mCureentAngla = mCureentAngla;
        if(sensorManager==null){
            sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
            //通过 getDefaultSensor 获得指南针传感器
            sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
            //为传感器管理者注册监听器,第三个参数指获取速度正常
            sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
        }
    }

    private int mCureentAngla=181;
    private Paint mBitmapPaint;
    private Paint mTextPaint;
    private Context context;
    public DemoZhiNaZhen(Context context) {
        this(context, null);
    }

    public DemoZhiNaZhen(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DemoZhiNaZhen(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context=context;
        mPaint = new Paint();
        mPaint.setDither(true);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(getResources().getDimension(R.dimen.dp_1));
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeJoin(Paint.Join.ROUND);

        mBitmapPaint = new Paint();
        mBitmapPaint.setDither(true);
        mBitmapPaint.setAntiAlias(true);

        mTextPaint = new Paint();
        mTextPaint.setDither(true);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(Color.GRAY);
        mTextPaint.setTextSize(getResources().getDimension(R.dimen.sp_12));

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeigth = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeigth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int x = mWidth / 2;
        int y = mHeigth / 2;
        int r = (int) (mWidth * 0.42);
        canvas.save();
        for (int i = 0; i < 120; i++) {
            if(i==0){
                mPaint.setColor(Color.RED);
                drawText("北",canvas);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }else if(i==30){
                mPaint.setColor(Color.RED);
                drawText("东",canvas);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }else if(i==60){
                mPaint.setColor(Color.RED);
                drawText("南",canvas);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }else if(i==90){
                mPaint.setColor(Color.RED);
                drawText("西",canvas);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }else if(i==5||i==10||i==20||i==25||i==15||i==35||i==40||i==45||i==50||i==55||i==65||i==70||i==75||i==80||i==85||i==95||i==100||i==105||i==110||i==115){
                mPaint.setColor(Color.BLACK);
                drawText(i*3+"",canvas);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }else{
                //绘制下层菊花
                mPaint.setColor(Color.GRAY);
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.1), mPaint);
            }
            canvas.rotate(360 / 120, x, y);
        }
        for (int i = 0; i < 360; i++) {
            if(mCureentAngla==i){
                canvas.drawLine(x, y - r, x, (float) (y - r + x * 0.2), mPaint);
            }
            canvas.rotate(360 / 360, x, y);
        }
        canvas.restore();
    }

    public void drawText(String string,Canvas canvas){

        //画中间文字
        String text = string;
        Rect textRect=new Rect();
        mTextPaint.getTextBounds(text,0,text.length(),textRect);
        int startX=getWidth()/2-textRect.width()/2;
        int textHeight=textRect.height();
        int baseLine=0;
        Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
        int dy=(fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
        baseLine= textHeight/2+dy;

        canvas.drawText(text,startX,baseLine,mTextPaint);
    }

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        switch (sensorEvent.sensor.getType()) {
            case Sensor.TYPE_ORIENTATION:
                //顺时针转动为正,故手机顺时针转动时,图片得逆时针转动
                toDegrees = (int) -sensorEvent.values[0];
                if( this.onAnglaChanged !=null){
                    onAnglaChanged.onChanged(toDegrees);
                }
                break;
        }

    }

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

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if(sensorManager!=null){
            sensorManager.unregisterListener(this);
        }
    }

    public interface OnAnglaChanged{
        void onChanged(int angla);
    }
    public OnAnglaChanged onAnglaChanged;
    public void setOnAnglaChanged(OnAnglaChanged onAnglaChanged){
        this.onAnglaChanged=onAnglaChanged;
    }
}

可以看到代码里面我留了setCureentAngla这个接口,这就是设置当前方位角的,我把求方位角的代码留在了activity中这不算是很好的封装(吃瓜群众:偷懒就是偷懒,还这么多借口)。
好吧,我承认是有那么一丢丢懒,但是我不改,哈哈哈。
下面是activity中的使用代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.easy.customeasytablayout.customviews.zhinanzhen.Main19Activity">
    <TextView
        android:id="@+id/tv_angla"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_80"
        android:textSize="@dimen/sp_24"
        android:textColor="@android:color/black"
        android:layout_centerHorizontal="true"/>
    <RelativeLayout
        android:layout_width="@dimen/dp_240"
        android:layout_height="@dimen/dp_240"
        android:layout_centerInParent="true">
        <com.easy.customeasytablayout.customviews.zhinanzhen.DemoZhiNaZhen
            android:id="@+id/test"
            android:layout_width="@dimen/dp_240"
            android:layout_height="@dimen/dp_240"
            android:layout_centerInParent="true"/>
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/iv_zhishi"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/dp_22"/>
    </RelativeLayout>

</RelativeLayout>


public class Main19Activity extends AppCompatActivity {

    private DemoZhiNaZhen test;

    private int fromDegrees = 0;
    private TextView mTvAngla;
    //31.2036,121.6012
    //31.1237,121.3536
    private PointF start = new PointF(31.1237f, 121.3536f);//起点
    private PointF end = new PointF(31.2036f, 121.6012f);//起点

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main19);
        test = (DemoZhiNaZhen) findViewById(R.id.test);
        mTvAngla = (TextView) findViewById(R.id.tv_angla);
        test.setCureentAngla((int) gps2d(31.1237f, 121.3536f, 31.2036f, 121.6012f));
        test.setOnAnglaChanged(new DemoZhiNaZhen.OnAnglaChanged() {
            @Override
            public void onChanged(int toDegrees) {
                mTvAngla.setText("" + Math.abs(toDegrees) + " 度");
                //让图片相对自身中心点转动,开始角度默认为0;此后开始角度等于上一次结束角度
                RotateAnimation ra = new RotateAnimation(fromDegrees, 
                toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                ra.setInterpolator(new LinearInterpolator());
                //动画时间200毫秒
                ra.setDuration(Math.abs(fromDegrees-toDegrees));
                ra.setFillAfter(true);
                test.startAnimation(ra);
                fromDegrees = toDegrees;

            }
        });
    }

    private float gps2d(float lat_a, float lng_a, float lat_b, float lng_b) {
        float d = 0;
        lat_a = (float) (lat_a * Math.PI / 180);
        lng_a = (float) (lng_a * Math.PI / 180);
        lat_b = (float) (lat_b * Math.PI / 180);
        lng_b = (float) (lng_b * Math.PI / 180);
        d = (float) (Math.sin(lat_a) * Math.sin(lat_b) + 
              Math.cos(lat_a) * Math.cos(lat_b) * Math.cos(lng_b - lng_a));
        d = (float) Math.sqrt(1 - d * d);
        d = (float) (Math.cos(lat_b) * Math.sin(lng_b - lng_a) / d);
        d = (float) (Math.asin(d) * 180 / Math.PI);
        System.out.println("yanjin-------方位角--" + d);
        return d;
    }
}

效果图:


1532929065246.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容

  • 公司做饭的大姐请假回家了,另外做饭的师傅一个人有点忙,公司准备再招聘一人,随着招聘信息的发布,陆陆续续的来了好几个...
    优妈读绘本阅读 408评论 1 2
  • 1, 关于好奇。生活中我还算是一个喜欢好奇的人,凡事喜欢追根究底,但在家庭生活上我觉得我做的并不好。比如老公下班回...
    Xuequi阅读 170评论 0 0
  • 北京已经进入一年中最好的季节里,但是因为她身体的原因,整整两天都闷在家里。心里极其渴望的能开车到郊外去看看转转...
    Kennyiti阅读 132评论 0 0
  • 01 以前的手机还是一部只能打电话的机器,而现在的手机却早已经成为了一部小电脑,无论何时何地它对我们的吸引力始终是...
    阅动视界阅读 230评论 1 4