주식 차트처럼 올라갔다 내려가는 EditText 구현하기

김태영·2024년 7월 22일
0

TIL

목록 보기
54/70
post-thumbnail

오늘 공부한 것

- 알고리즘 마법의 엘리베이터 풀이
- 스탠다드반 과제 마무리

구현해볼 것

카카오톡이나 채팅앱들을 보면 메시지를 입력하는 부분이 화면 하단에 존재한다. 입력창을 눌렀을 때 키보드가 올라오면 메시지를 입력하는 부분도 같이 올라오는 형태로 많이 구현되어있다.

이걸 구현하는 방법으로는 여러가지가 있겠지만, 그중에서도 오늘 나는 2가지 정도만 알아보려고 한다.

1. windowSoftInputMode

"EditText 키보드 위에 고정"이라고 검색했을 때 가장 많이 나오는 방법이다. 간단하게 속성 몇 개 추가만 해주면 안드로이드가 알아서 키보드 외의 화면을 올리거나 줄여준다.

AndroidManifest.xml

<activity
    android:name=".activity.DetailActivity"
    android:exported="false"
    android:windowSoftInputMode="adjustResize" />

원래는 android:windowSoftInputMode="adjustResize"만 주면 적용이 되지만, 나는 루트 뷰가 ConstraintLayout이라 그런지 잘 적용되지 않았다. 따라서 루트 뷰에 추가적으로 android:fitsSystemWindows="true" 속성을 작성해주었다.

activity_detail.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"
    android:id="@+id/main"
    android:fitsSystemWindows="true">

2. GlobalLayoutListener

키보드가 올라온 상태인지 아닌지를 알 수 있는 방법은 다양하겠지만, 나는 처음 보여지는 화면의 크기와 키보드가 올라왔을 때의 화면의 크기가 다르다는 점을 이용했다. 현재 보여지고 있는 화면이 처음 렌더링 됐을 때의 화면보다 작다면, 무언가에 가려졌다는 뜻이고 이 말은 곧 키보드가 올라왔다는 뜻이기도 하다! 이걸 구현하기 위해 viewTreeObserver의 GlobalLayoutListener를 사용해주었다.

사실 처음에는 constraintSet을 이용하지 않고, EditText의 y축 만을 움직였었는데 다른 뷰와의 제약 조건이 잘 적용되지 않는 이슈가 있었다. ConstraintLayout은 뷰와 뷰 사이의 관계를 기준으로 화면이 구성되기 때문에 y축만 띡 바꾸는 게 아니라 뷰와 뷰 사이 관계까지 생각해서 적용을 해야된다고 한다. 이게 또 모든 뷰들에 대해 id 값이 있어야 하는 이유이기도 하다.

아무튼 코드는 키보드의 높이를 구한다음, EditText 아래쪽에 그만큼의 추가 마진을 주는 방식이다. 냅다 위치를 조정하는 것보단 마진으로 조절하는 게 더 간단하다고 한다.

private fun handleInputChat() {
    val rootView = findViewById<ConstraintLayout>(R.id.main)
    rootView.viewTreeObserver.addOnGlobalLayoutListener(object :
        ViewTreeObserver.OnGlobalLayoutListener {
        private var isKeyboardShown = false

        override fun onGlobalLayout() {
            val r = Rect()
            rootView.getWindowVisibleDisplayFrame(r)
            val heightDiff = rootView.bottom - r.bottom
            isKeyboardShown = heightDiff > 100
            val constraintSet = ConstraintSet()
            constraintSet.clone(rootView)
            constraintSet.setMargin(
                R.id.layout_chat,
                ConstraintSet.BOTTOM,
                if (isKeyboardShown) heightDiff else 20
            )
            constraintSet.applyTo(rootView)
        }
    })
}
profile
화이팅

0개의 댓글