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를 잘못 달아서 난 오작동임을 알아내고 허탈했다.😄
📌 오작동을 맞닥드렸을 때, 로직에 문제가 없음을 확인했다면 올바른 클래스, 리스너, 매서드 등을 사용했는지 다시 체크해보자!
참고 사이트 📄
제 글이 당신에게 도움이 되었길 바랍니다.
추가적인 질문은 언제든지 환영해요.
인상깊게 보셨다면 바로 위에 있는 광고 한 번만 클릭해주세요!
정말 큰 힘이 됩니다~! 🤠
'📜 TIL' 카테고리의 다른 글
[Android] 로그인 시 아이디 창에 적힌 글자 한 번에 clear하는 기능 구현 (0) | 2023.03.14 |
---|---|
Fragment에서 뷰바인딩(ViewBinding)해주는 방법과 적용 (0) | 2023.03.12 |
[Android] NullPointerException -ViewTreeObserver.dispatchOnGlobalLayout (0) | 2023.03.06 |
[Android] Navigation으로 Fragment간 이동을 편리하게 만들어주기 (0) | 2023.03.01 |
[Android] 서버 로그인 시 비밀번호 암호화 적용해주기 (0) | 2023.02.27 |