You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用onDraw方法绘制指南针以开发Kotlin安卓GPS航点应用

Kotlin实现自定义指南针及GPS航点应用开发方案

一、onDraw绘制指南针实现步骤

1. 自定义View基础配置

首先创建继承自View的自定义指南针类,提前声明所需属性:

class CompassView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    // 刻度画笔
    private val dialPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.BLACK
        strokeWidth = 2f
        style = Paint.Style.STROKE
    }
    // 文字画笔
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.BLACK
        textSize = 32f
        textAlign = Paint.Align.CENTER
    }
    // 指针画笔
    private val needlePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.RED
        style = Paint.Style.FILL
    }
    // 当前方位角,0代表正北
    var currentAzimuth = 0f
        set(value) {
            field = value
            invalidate() // 数值更新后自动触发重绘
        }
    private var viewSize = 0
}

2. 测量与布局处理

重写onMeasure方法保证指南针始终为正方形,适配不同布局尺寸:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val width = MeasureSpec.getSize(widthMeasureSpec)
    val height = MeasureSpec.getSize(heightMeasureSpec)
    viewSize = min(width, height)
    setMeasuredDimension(viewSize, viewSize)
}

3. 核心onDraw绘制逻辑

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val centerX = viewSize / 2f
    val centerY = viewSize / 2f
    val radius = viewSize / 2f * 0.9f

    // 移动画布原点到View中心
    canvas.save()
    canvas.translate(centerX, centerY)
    // 按当前方位角反向旋转画布,实现指南针跟随设备方向转动
    canvas.rotate(-currentAzimuth)

    // 绘制外圈刻度
    for (angle in 0 until 360 step 5) {
        val isLongTick = angle % 10 == 0
        val tickLength = if (isLongTick) 40f else 20f
        canvas.drawLine(
            0f, -radius,
            0f, -radius + tickLength,
            dialPaint
        )
        // 每30度标注方向/度数
        if (angle % 30 == 0) {
            val text = when(angle) {
                0 -> "N"
                90 -> "E"
                180 -> "S"
                270 -> "W"
                else -> angle.toString()
            }
            canvas.drawText(
                text,
                0f,
                -radius + tickLength + 40f,
                textPaint
            )
        }
        canvas.rotate(5f)
    }

    // 绘制中心正北指向指针
    val path = Path()
    path.moveTo(0f, -radius + 60f)
    path.lineTo(-30f, 0f)
    path.lineTo(30f, 0f)
    path.close()
    canvas.drawPath(path, needlePaint)

    canvas.restore()
}

4. 方位角数据绑定

通过系统传感器获取实时方位角更新即可:

  • 通过SensorManager注册TYPE_ROTATION_VECTOR类型传感器
  • 监听传感器回调,调用SensorManager.getOrientation()方法计算得到方位角,转换为角度单位后赋值给自定义View的currentAzimuth属性即可自动刷新视图

二、GPS航点应用开发建议

  • 权限处理:提前申请ACCESS_FINE_LOCATION定位权限,Android 12及以上版本需额外处理精确定位权限申请,后台持续定位需求需申请ACCESS_BACKGROUND_LOCATION权限
  • 定位实现:使用FusedLocationProviderClient获取定位,相比原生LocationManager功耗更低、定位精度更稳定
  • 航点存储:使用Room数据库存储航点数据,支持存储航点名称、经纬度、标记时间、备注等结构化数据,查询和修改效率更高
  • 导航功能:通过经纬度坐标计算当前位置到目标航点的直线距离、相对方位,和指南针方向结合,直观提示用户前往目标的行进方向
  • 异常兼容:添加无GPS信号、传感器精度过低场景的用户提示,传感器精度低时可提示用户按8字形晃动设备完成校准

内容的提问来源于stack exchange,提问作者Chris Marshall Iheacho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 16:54:02