CustomView, Rotating Image
CustomView
CustomView를 사용해서 노래 볼륨을 조절하는 회전식 버튼을 만들어보자.
이번에 만들어볼 커스텀 뷰는 커스텀 이미지 뷰이다.
- 우선 AppCompatImageView 를 상속받는 코틀린 클래스를 만들자.
// VolumeControlView.kt
class VolumeControlView(context: Context, attr: AttributeSet?) : AppCompatImageView(context, attr) {
private var mx = 0.0f
private var my = 0.0f
private var tx = 0.0f
private var ty = 0.0f
private var angle = 0.0f
// 리스너 객체를 맴버로 포함
private var listener: VolumeListener? = null
// 리스너를 구현한 외부 클래스에서 기능을 사용하게 함
interface VolumeListener{
public fun onChanged(angle: Float):Unit
}
// 외부 클래스에서 생성한 리스너를 연결시키는 함수
fun setVolumeListener(listener: VolumeListener){
this.listener = listener
}
// 현재 각도를 구해주는 함수 (x1: x좌표, y1: y좌표)
private fun getAngle(x1:Float, y1:Float):Float {
mx = x1-(width /2.0f)
my = (height/2.0f)-y1
return (atan2(mx, my) *180.0f/ PI).toFloat() // arctan 삼각함수로 각도 계산
}
// 터치가 발생하면
override fun onTouchEvent(event: MotionEvent?): Boolean {
return if(event != null){
tx = event.getX(0) // 이미지 뷰 기준 현재 x 좌표
ty = event.getY(0) // 이미지 뷰 기준 현재 y 좌표
angle = getAngle(tx,ty) // 각도
invalidate() // onDraw()를 호출
listener?.onChanged(angle) // 리스너에서 오버라이딩 된 함수 실행 (사용하는 클래스의 목적에 맞게 구현된 함수)
true // 성공 반환
}else false // 실패 반환, 부모 함수 실행
}
// 화면을 다시 그려줌
override fun onDraw(canvas: Canvas?) {
canvas?.rotate(angle, width/2.0f, height/2.0f) // 이미지 회전
super.onDraw(canvas)
}
}
- 커스텀 이미지 뷰 클래스를 잘 작동했다면 xml에서 만들었던 커스텀 뷰를 사용해보자.
<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.jyh.juyonghan201811567.VolumeControlView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="100dp"
android:src="@drawable/knob"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/stopButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_stop_24"
app:layout_constraintEnd_toStartOf="@+id/playButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/playButton"
tools:layout_editor_absoluteY="375dp" />
<ImageButton
android:id="@+id/pauseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_pause_24"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/playButton"
app:layout_constraintTop_toTopOf="@id/playButton"
tools:layout_editor_absoluteY="375dp" />
<ImageButton
android:id="@+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_play_arrow_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/pauseButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/stopButton"
app:layout_constraintTop_toBottomOf="@+id/imageView"
app:layout_constraintVertical_bias="0.182" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 메인 엑티비티를 작성해 버튼의 각도로 음악 볼륨을 조절할 수 있게 만들어보자.
// MainActivity.kt
class MainActivity : AppCompatActivity() {
private var mediaPlayer:MediaPlayer? = null
private var vol = 0.0f
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initLayout() // 레이아웃 초기화
}
private fun initLayout() {
val imageView = findViewById<VolumeControlView>(R.id.imageView)
// 회전 버튼의 리스너 구현
imageView.setVolumeListener(object: VolumeControlView.VolumeListener {
// 현재 각도(angle)를 볼륨으로 변환, 적용
override fun onChanged(angle: Float) {
vol = if( angle>0 ) angle/360 else (360+angle)/360
mediaPlayer?.setVolume(vol,vol)
}
})
// 버튼들 구현
val playButton = findViewById<ImageButton>(R.id.playButton)
playButton.setOnClickListener{
if(mediaPlayer == null){
mediaPlayer = MediaPlayer.create(this,R.raw.song)
mediaPlayer?.setVolume(vol,vol)
}
mediaPlayer?.start()
}
val pauseButton = findViewById<ImageButton>(R.id.pauseButton)
pauseButton.setOnClickListener {
mediaPlayer?.pause()
}
val stopButton = findViewById<ImageButton>(R.id.stopButton)
stopButton.setOnClickListener{
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
}
}
}