如何使用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
相关产品推荐
相关产品推荐

