불현득 생각이 나서 코틀린 연습 겸 샘플용으로 만들었습니다~
센서처리는 다음 블로그를 참고했어요.
http://swlock.blogspot.com/2017/10/android-compass.html
Android Compass (나침반)
안드로이드에서 나침반 만들기 1. 준비 한때 AR(증강 현실) 어플들이 유행하던 시절이 있었는데, 막상 그때는 관심이 없다가 지금에서야 정리하게 되네요. 시작하기전에 알아 두어야 하는 기본 개념이 3가지가 있습니다. Azimuth, Pit...
swlock.blogspot.com
MainActivity는 다음과 같이 되어있어요.
Listener를 별도로 빼고 interface로 연결해주면 좀 더 깔끔하게 작성할 수 있습니다.
class MainActivity : AppCompatActivity(), SeekBarToView, SensorToView{
private val sensorImpl = SensorEventListenerImpl(this)
private lateinit var sm: SensorManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sm = getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
override fun onResume() {
super.onResume()
sm.registerListener(sensorImpl, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)
sm.registerListener(sensorImpl, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sm.unregisterListener(sensorImpl)
}
// from Listener
override fun onDegreeChanged(degree: Float) {
mainCanvas.degree = degree
}
}
나침반 역할을 하는 View는 다음과 같이 CustomView로 만들어줬습니다.
간단한 삼각함수로 절대좌표를 구했어요. Canvas의 상대 사이즈로 만들어졌기 때문에 여기에서 더 코드 보완이 필요하겠네요.
private const val FIRST_RING_WIDTH = 10f
class Compass(ctx: Context, attr: AttributeSet?) : View(ctx, attr) {
var degree: Float = 0.0f
set(value) {
// 90˚ offset
field = value + 90f
invalidate()
}
constructor(ctx: Context) : this(ctx, null)
private val blackCirclePaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val whiteCirclePaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val indicatorPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
init {
// Paint for black outer circle
blackCirclePaint.color = Color.BLACK
// Paint for white inner circle
whiteCirclePaint.color = Color.WHITE
// line indicator
indicatorPaint.strokeWidth = 5f
indicatorPaint.strokeCap = Paint.Cap.ROUND
}
override fun onDraw(canvas: Canvas?) {
canvas?.let {
myDraw(it)
}
}
private fun myDraw(canvas: Canvas) {
val halfHeight = canvas.height / 2f
val radius = canvas.width / 2f
canvas.drawCircle(radius, halfHeight, radius, blackCirclePaint)
canvas.drawCircle(radius, halfHeight, radius - FIRST_RING_WIDTH, whiteCirclePaint)
canvas.drawLine(radius, halfHeight, radius + calculateXWithDegree(radius, degree), halfHeight + calculateYWithDegree(radius, degree), indicatorPaint)
}
private fun calculateXWithDegree(r: Float, degree: Float): Float {
// a/r = cosθ
return r * Math.cos(Math.toRadians(degree.toDouble())).toFloat()
}
private fun calculateYWithDegree(r: Float, degree: Float): Float {
// b/r = sinθ
return r * Math.sin(Math.toRadians(degree.toDouble())).toFloat()
}
}
전체 소스는 아래를 참고해주세요!
'소프트웨어 > 안드로이드' 카테고리의 다른 글
[Android Studio] 파일을 잘못 불러오는 경우 (2) | 2019.11.05 |
---|---|
[Android Studio] Javadoc 생성 시 인코딩 에러 (0) | 2019.09.30 |
[Android] 안드로이드 웹 주소 URL로 브라우저 실행하기 (2) | 2019.09.16 |
[Android] AIDL을 구현해보자! (0) | 2019.09.06 |
화면 사이즈 확인 테스트 코드 (0) | 2019.04.16 |