불현득 생각이 나서 코틀린 연습 겸 샘플용으로 만들었습니다~
센서처리는 다음 블로그를 참고했어요.
http://swlock.blogspot.com/2017/10/android-compass.html
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 |