📜 TIL

Soft Keyboard(virtual keyboard) 띄워졌을 때 키보드 바로 위에 버튼이 보여지도록 만들기

둥굴둥굴둥굴레차 2023. 3. 10. 10:04

To-do list 📌

  • Login화면의 ID, PW글자를 text형식에서 img로 바꾸기
  • Soft Keyboard(virtual keyboard) 띄워졌을 때 키보드 상단에 Enter버튼이 보여지도록 만들기
    • 결과물
  • 아이디 혹은 패스워드 입력창을 클릭 하면 키보드가 올라오면서 Enter버튼이 보여짐
    • 키보드가 내려가면 Enter버튼이 사라짐
  • 키보드가 올라왔을 때 sns로그인하는 버튼과 회원가입 버튼은 사라진 상태여야 함

 

 

오늘 공부한 내용 📋

  • Soft Keyboard(virtual keyboard)가 띄워졌을 때 혹은 그렇지 않을 때를 인식하는 로직을 구현하는 법을 배움
class LoginFragment : Fragment() {

    private lateinit var loginViewModel: LoginViewModel
    private var binding: FragmentLoginBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
				// ViewBinding
        var binding: FragmentLoginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)
        //binding.setLifecycleOwner { viewLifecycleOwner.lifecycle }

        val showDefaultHeight = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 150f,
            resources.displayMetrics
        ).toInt()

        val hideDefaultHeight = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 150f,
            resources.displayMetrics
        ).toInt()

				// addOnGlobalLayoutListener: 레이아웃에 변화가 있을 때 감지해주는 리스너
        binding.loginLayout.viewTreeObserver.addOnGlobalLayoutListener {

						// loginLayout이란 ID를 가진 레이아웃의 높이
            val viewHeight: Int = binding.loginLayout.height
						
						// loginLayout이란 ID를 가진 레이아웃보다 상위에 있는 레이아웃의 높이
						// fragment_login.xml의 최상위 레이아웃의 ID는 loginLayout이기 때문에
						// rootView는 해당 xml을 담고있는 container의 높이를 감지하는 것 같다
            val rootHeight: Int = binding.loginLayout.rootView.height
            
						val diff = rootHeight - viewHeight

            if (diff > showDefaultHeight) {
                setSNSLoginUIVisibility(binding, View.GONE)
            } else if (diff < hideDefaultHeight) {
                // 바로 enter버튼을 보여주니 버튼이 생성되고 사라질 때 
								// 약간 어색하게 움직여서 postDelayed를 사용해 delay를 주었다
								Handler(Looper.getMainLooper()).postDelayed(Runnable {
                    setSNSLoginUIVisibility(
                        binding,
                        View.VISIBLE
                    )
                }, 10)
            }
        }

        return binding.root
    }

    private fun setSNSLoginUIVisibility(binding: FragmentLoginBinding, visibility: Int) {
				
				// 파라미터로 들어오는 visibility가 View.VISIBLE이냐 View.GONE이냐에 따라서
				// sns로그인 버튼과 회원가입 버튼이 보여지거나 보여지지 않게 되고
        binding.facebookLogin.visibility = visibility
        binding.naverLogin.visibility = visibility
        binding.googleLogin.visibility = visibility
        binding.join.visibility = visibility

				// 동시에 파라미터로 들어오는 visibility에 따라 
				// enter버튼이 보여지지 않거나 보여지게 된다
        if (visibility == View.VISIBLE) {
            binding.enterButton.visibility = View.GONE
        } else if (visibility == View.GONE) {
            binding.enterButton.visibility = View.VISIBLE
        }
    }

}
  •  ViewTreeObserver
    • View가 화면에 그려진 뒤 높이를 가져와야 하므로 화면에 그려졌다는 알림을 받을 수 있는 Observer

 

궁금한 내용 / 부족한 내용 🧐

더 쉬운 방법으로 Soft Keyboard에 대해 인식할 수 있는 로직이 있는지 찾아보려 함

 

 

느낀 점 🤔

기존의 ODDICT앱의 Login화면에 대해 클론코딩하는 시간을 가지고 있다. 최대한 ODDICT소스를 참고하지 않으며 구현하고 있기 때문에, 나만의 코딩 스타일을 찾을 수 있을 것 같다.

오늘은 소소한 부분들을 수정하였다. ID와 PW란을 기존 Text형식에서 이미지 파일로 대체하였다.

또한 ID를 입력할 수 있는 EditText 부분을 터치했을 때 팝업되는 Soft Keyboard(virtual keyboard)위에 Enter버튼이 출력되도록 만들었다.

그런데 이 때 PW를 입력하기 위해 PW의 EditText부분을 터치하면 Enter버튼이 사라지는 에러를 수정하느라 애먹었다.

그런데 로직이 틀렸던 것이 아니라 잘못된 리스너를 사용한 탓이었던 것을 깨닫고 허탈했다.😅

요약하자면 레이아웃의 변화를 알아차릴 수 있도록 RootView에 viewTreeObserver를 달고,

해당 변화를 읽을 수 있도록 addOnGlobalLayoutListener 를 달았어야 했는데

addOnGlobalFocusChange Listener를 달아줬었다.

엄청 헤매었는데 Listener를 잘못 달아서 난 오작동임을 알아내고 허탈했다.😄

 

📌 오작동을 맞닥드렸을 때, 로직에 문제가 없음을 확인했다면 올바른 클래스, 리스너, 매서드 등을 사용했는지 다시 체크해보자!

 

참고 사이트 📄

 

How do I detect if software keyboard is visible on Android Device or not?

Is there a way in Android to detect if the software (a.k.a. "soft") keyboard is visible on screen?

stackoverflow.com

 


 

제 글이 당신에게 도움이 되었길 바랍니다.

추가적인 질문은 언제든지 환영해요.

 

인상깊게 보셨다면 바로 위에 있는 광고 한 번만 클릭해주세요!

정말 큰 힘이 됩니다~! 🤠