728x90
반응형

Activity에서 키보드가 올라오고 화면크기를 변경하기 위해 AndroidManifest.xml에 android:windowSoftInputMode에 adjustResize를 설정해줍니다.



위에 화면처럼 EditText를 선택하고 키보드가 올라오면 아래 로그인 버튼이 보이지 않아 사용자가 스크롤 해야 하는 문제가 있습니다.

(스크롤 하기 완전 귀찮아..)


이번 포스팅에서는 키보드가 보여질 때 화면을 키보드 크기 만큼 위로 스크롤 하는 방법에 대해 설명하고자 합니다.


andorid softkeyboard height라는 키워드로 구글링을 하던 중에 Keyboard Handling on Android 글을 보고 키보드가 보이고 사라지는 이벤트를 만들었습니다.


제가 예제로 만든 앱의 layout은 아래와 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sv_root"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="20dp">


<ImageView
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_marginTop="40dp"
android:src="@mipmap/ic_launcher" />

<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="@string/hint_id"
android:inputType="text"
android:lines="1"
android:textSize="24sp" />

<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="@string/hint_password"
android:inputType="textPassword"
android:lines="1"
android:textSize="24sp" />

<Button
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="@string/login" />

<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:paddingEnd="8dp"
android:paddingStart="8dp">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sign_up" />

<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/forgot_your_password" />
</LinearLayout>
</LinearLayout>

</ScrollView>

키보드가 보여질 때 화면을 스크롤 하기 위해서 최상단에는 ScrollView를 추가했습니다.



저는 KeyboardVisibilityUtils라는 클래스를 만들고 Activity에서 가져다 사용 했습니다.

import android.graphics.Rect
import android.view.ViewTreeObserver
import android.view.Window

class KeyboardVisibilityUtils(
private val window: Window,
private val onShowKeyboard: ((keyboardHeight: Int) -> Unit)? = null,
private val onHideKeyboard: (() -> Unit)? = null
) {

private val MIN_KEYBOARD_HEIGHT_PX = 150

private val windowVisibleDisplayFrame = Rect()
private var lastVisibleDecorViewHeight: Int = 0


private val onGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
window.decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame)
val visibleDecorViewHeight = windowVisibleDisplayFrame.height()

// Decide whether keyboard is visible from changing decor view height.
if (lastVisibleDecorViewHeight != 0) {
if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
// Calculate current keyboard height (this includes also navigation bar height when in fullscreen mode).
val currentKeyboardHeight = window.decorView.height - windowVisibleDisplayFrame.bottom
// Notify listener about keyboard being shown.
onShowKeyboard?.invoke(currentKeyboardHeight)
} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
// Notify listener about keyboard being hidden.
onHideKeyboard?.invoke()
}
}
// Save current decor view height for the next call.
lastVisibleDecorViewHeight = visibleDecorViewHeight
}

init {
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}

fun detachKeyboardListeners() {
window.decorView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
}

visibleDecorViewHeight는 현재 화면의 height 값입니다.

만약 키보드가 올라와 있는 상태라면 visibleDecorViewHeight는 키보드가 올라오기 전 height보다 작습니다.

if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
// Calculate current keyboard height (this includes also navigation bar height when in fullscreen mode).
val currentKeyboardHeight = window.decorView.height - windowVisibleDisplayFrame.bottom
// Notify listener about keyboard being shown.
onShowKeyboard?.invoke(currentKeyboardHeight)
} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
// Notify listener about keyboard being hidden.
onHideKeyboard?.invoke()
}

이전에 보여준 화면 height현재 화면 height + 최소 키보드 크기 값 보다 크면 키보드가 올라온 것으로 보고 키보드가 보였다는 이벤트를 전달하고

이전에 보여준 화면 height + 최소 키보드 크기 값현재 화면 height 보다 작으면 키보드가 내려간 것으로 보고 키보드가 사라졌다는 이벤트를 전달 합니다.


그리고 MainActivity는 아래처럼 작성했습니다.

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

private lateinit var keyboardVisibilityUtils: KeyboardVisibilityUtils

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
keyboardVisibilityUtils = KeyboardVisibilityUtils(window,
onShowKeyboard = { keyboardHeight ->
sv_root.run {
smoothScrollTo(scrollX, scrollY + keyboardHeight)
}
})
}

override fun onDestroy() {
keyboardVisibilityUtils.detachKeyboardListeners()
super.onDestroy()
}


onCreate에서 KeyboardVisibilityUtils클래스를 만들 때 인자로 window를 전달하고 onShowKeyboard(키보드가 보여질 때 해당 코드가 호출)를 통해 키보드가 보여지는 이벤트를 받아서 ScrollView를 keyboardHeight만큼 스크롤 하고 있습니다.



이제 EditText를 선택하면 자동으로 화면이 위로 스크롤 됩니다.



출처: https://pspdfkit.com/blog/2016/keyboard-handling-on-android/


android keyboard handling

android keyboard scroll up

android keyboard event

728x90
반응형

+ Recent posts