안드로이드 소프트 키보드 숨기기
앱을 사용하다보면 사용자 텍스트 입력이 필요한 필드를 입력하다 필드 바깥쪽을 터치 시 소프트 키보드가 숨겨지는 모습을 볼 수 있다. 안드로이드의 경우 그런 동작이 EditText
를 사용한다고 해서 자동으로 적용되지 않기 때문에 그것을 적용하는 방법을 작성해본다.
적용 전
<?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:id="@+id/layout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tf_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="입력 필드 1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tf_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="입력 필드 2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tf_1">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Random text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tf_2" />
</androidx.constraintlayout.widget.ConstraintLayout>
EditText
바깥을 클릭해도 키보드가 사라지지 않는다.
키보드를 숨기는 방법
fun View.hideSoftKeyboard() {
val inputMethodManager = getSystemService(context, InputMethodManager::class.java)
inputMethodManager?.hideSoftInputFromWindow(windowToken, 0)
}
View
의 확장 함수를 작성해 hideSoftInputFromWindow
를 호출해 키보드를 숨길 수 있다. 이를 상위 ViewGroup
의 onTouchEvent
를 override
해서 클릭 이벤트를 감지해서 호출하면 적절한 상황에서 키보드를 숨길 수 있다.
class HideKeyboardConstraintLayout : ConstraintLayout {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
private var startX = 0F
private var startY = 0F
private var lastClicked = 0L
override fun onTouchEvent(event: MotionEvent?): Boolean {
event?.let {
when (it.action) {
MotionEvent.ACTION_DOWN -> {
Log.d("click", "${event.x}, ${event.y}")
startX = event.x
startY = event.y
lastClicked = System.currentTimeMillis()
}
MotionEvent.ACTION_UP -> {
Log.d("up", "${event.x}, ${event.y}")
val endX = event.x
val endY = event.y
val currClick = System.currentTimeMillis()
if (isClick(startX, startY, endX, endY, lastClicked, currClick)) {
performClick()
}
}
}
}
return super.onTouchEvent(event)
}
override fun performClick(): Boolean {
this.hideSoftKeyboard()
this.clearFocus()
return super.performClick()
}
private fun isClick(
startX: Float,
startY: Float,
endX: Float,
endY: Float,
lastClicked: Long,
currClick: Long
): Boolean {
val diffX = abs(startX - endX)
val diffY = abs(startY - endY)
val diffTime = currClick - lastClicked
return diffX <= CLICK_POS_THRESHOLD && diffY <= CLICK_POS_THRESHOLD && diffTime <= CLICK_TIME_THRESHOLD
}
companion object {
private const val CLICK_POS_THRESHOLD = 200
private const val CLICK_TIME_THRESHOLD = 400L
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.mylittleproject.demoapplication.HideKeyboardConstraintLayout 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:id="@+id/layout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:padding="16dp"
tools:context=".MainActivity">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tf_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="입력 필드 1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tf_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="입력 필드 2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tf_1">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Random text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tf_2" />
</com.mylittleproject.demoapplication.HideKeyboardConstraintLayout>
android:clickable
과 android:focusable
을 true
로 설정한다.
적용 후
EditText
바깥 쪽을 클릭하니 키보드가 사라진다.
Comments