android自定义指南针罗盘学习笔记

时间:2024-04-11 13:23:21

1.需求分析

这种纯图形的罗盘,首先考虑的是用继承View的方式,画圆 画刻度 画方向 画度数

2.代码实现

a.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context="com.yuncai.menjin.compassdemo.MainActivity">

    <com.yuncai.menjin.compassdemo.CompassView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

b.java

package com.yuncai.menjin.compassdemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Function:
 * Created by TianMing.Xiong on 18-10-26.
 */

public class CompassView extends View {

    private Paint circlePaint;
    private Paint textPaint;
    private int textHeight;
    private Paint markerPaint;

    public CompassView(Context context) {
        super(context);
        initCompass();
    }

    public CompassView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initCompass();
    }


    private void initCompass() {
        setFocusable(true);

        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(Color.RED);
        circlePaint.setStrokeWidth(1);
        circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);

        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.BLUE);
        textHeight = (int) textPaint.measureText("yY");

        markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        markerPaint.setColor(Color.GREEN);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredWidth = measureSize(widthMeasureSpec);
        int measuredHeight = measureSize(heightMeasureSpec);
        int radius = Math.min(measuredWidth,measuredHeight);
        setMeasuredDimension(radius,radius);
    }

    private int measureSize(int measureSpec) {
        int result ;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if(mode == MeasureSpec.UNSPECIFIED){
            result = 200;
        }else {
            result = size;
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // view中心点
        int px = getMeasuredWidth() / 2;
        int py = getMeasuredHeight() / 2;
        // 圆半径
        int radius = Math.min(px,py);
        // 画圆
        canvas.drawCircle(px,py,radius,circlePaint);
        // 保存图形
        canvas.save();// save -->restore成对出现
        // 旋转画布,从顶部开始画起
        canvas.rotate(0,px,py);
        //
        int textWidth = (int) textPaint.measureText("W");
        // 文字中心点,为什么要这样计算?因为直接在x=textWidth处画文字会导致这个文字在该点的右边,要使文字刚好中心点在该点就需要设置为textWidth/2
        int cardinalX = px - textWidth / 2;
        int cardinalY = py - radius + textHeight;
        // 每15度绘制一个短线刻度(360/15=24)
        for (int i = 0; i < 24; i++) {
            // 画刻度,坐标(px,0)->(px,10)即从上往下画,刻度长为10
            canvas.drawLine(px,py-radius,px,py-radius+10,markerPaint);
            canvas.save();// 保存之前的画布状态
            // 把画布的原点移动到(0,10),相当于原点坐标下移10,则原来的纵坐标值就相对变大了10(实际坐标值大小不变)
            canvas.translate(0,10);
            // 绘制四个方向文字(N E S W),坐标(cardinalX,cardinalY),每隔90度即15*6
            if(i % 6==0){
                String dirString = "";
                switch (i){
                    case 0:
                        dirString = "N";
                        break;
                    case 6:
                        dirString = "E";
                        break;
                    case 12:
                        dirString = "S";
                        break;
                    case 18:
                        dirString = "W";
                        break;
                }
                canvas.drawText(dirString,cardinalX,cardinalY,textPaint);

            }else if(i % 3 ==0){// 在非标注方向的刻度上每隔45度画上度数
                String angle = String.valueOf(i * 15);
                float angleTextWidth = textPaint.measureText(angle);
                float angleTextX = px - angleTextWidth / 2;
                float angleTextY = py - radius+textHeight;// 为何不是0而是textHeight?文字是从下往上画的,所以减去文字高度刚好使文字在该点下方
                canvas.drawText(angle,angleTextX,angleTextY,textPaint);
            }
            canvas.restore();//把当前画布返回(调整)到上一个save()状态之前
            // 旋转画布为正即逆时针旋转,画文字就相当于顺时针画
            canvas.rotate(15,px,py);
        }
        canvas.restore();

    }
}

 

3.效果图

android自定义指南针罗盘学习笔记