-
안드로이드 EditText 가상키보드 없애기 - RadioButton편카테고리 없음 2020. 10. 12. 17:39
(현재 글의 코드 예시는 코틀린으로 작성되었습니다.)
최종 목표: 아래 동영상처럼 동작하는 코드 만들기.
완성된 동작 저번 글에서 EditText를 누르면 생기는 가상키보드가 흰 바탕을 클릭했을 때 자동으로 접히게 하는 방법을 알아보았다.
이전 글 보기: nerdymint.tistory.com/2
아래 동영상은 별다른 설정을 하지 않은 라디오버튼의 동작이다. 가상키보드를 자동으로 접어주지는 않는다.
아무 설정도 하지 않은 기본 라디오버튼의 동작. 먼저, 저번 글에서 한 것 처럼 EditText의 OnFocusChangeListener를 set해야 한다.
이전 글 보기: nerdymint.tistory.com/2
EditText가 여러개일 때, 코드를 재활용하려면 아래 코드처럼 OnFocusChangeListener객체를 미리 만들어놓고 EditText에 갖다 붙이기만 하는 방법을 추천한다.
Kotlin Extension의 기능을 이용하여 findViewById는 사용하지 않았으며, et1와 et2는 각각 EditText객체이다.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val editTextListener = OnFocusChangeListener { v, hasFocus -> if (!hasFocus) { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(v.windowToken, 0) } } et1.onFocusChangeListener = editTextListener et2.onFocusChangeListener = editTextListener } }
(여기까지는 저번 글의 내용과 동일하다.)
그 다음 과정은 xml의 focusableInTouchMode 설정이다. (이것도 어쩌면 저번 글과 비슷할지도...)
이전 글 보기: nerdymint.tistory.com/2
저번 글의 맨 아래 몇 줄에서 언급한대로 부모 뷰에서 focusableInTouchMode 설정을 하더라도 버튼에서 또 따로 focusableInTouchMode설정을 해야된다. (이유는 알 수 없지만 TextView는 그냥 둬도 부모 뷰의 설정을 알아서 따라간다.) 라디오버튼의 경우도 마찬가지로 focusableInTouchMode설정을 따로 해준다.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout // 생략 android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" android:focusableInTouchMode="true"> <EditText android:id="@+id/et1" // 생략 /> <EditText android:id="@+id/et2" // 생략 /> <RadioGroup // 생략 > <RadioButton android:id="@+id/rb1" android:text="선택지1" android:focusableInTouchMode="true" // 생략 /> <RadioButton android:id="@+id/rb2" android:text="선택지2" android:focusableInTouchMode="true" // 생략 /> </RadioGroup> </androidx.constraintlayout.widget.ConstraintLayout>
위의 코드처럼 RadioButton에 focusableInTouchMode를 true로 설정했다.
이제 라디오버튼을 클릭하면 가상키보드가 사라진다. 그러나 Radio Button을 두 번 클릭해야 체크가 되는 새로운 문제가 생겼다.. 직접 보자.
라디오버튼을 두 번 눌러야 하는 문제가 발생. 마치 영상이 잠깐 멈췄다가 다시 재생되는 것 같지만 그렇지 않다. 라디오버튼의 문제이다.
해결방법: 포커스를 가지면 체크를 시켜주자.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val editTextListener = OnFocusChangeListener { v, hasFocus -> if (!hasFocus) { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(v.windowToken, 0) } } val radioButtonListener = OnFocusChangeListener { v, hasFocus -> if (hasFocus) { (v as RadioButton).isChecked = true } } et1.onFocusChangeListener = editTextListener et2.onFocusChangeListener = editTextListener rb1.onFocusChangeListener = radioButtonListener rb2.onFocusChangeListener = radioButtonListener } }
EditText는 포커스를 잃을 때 (not hasFocus) 가상키보드를 숨기고, RadioButton은 포커스를 얻을 때 (hasFocus) checked가 true가 된다.
OnFocusChangeListener는 포커를 가지게 될 때 뿐 아니라 포커를 잃을 때도 호출되기 때문에, 조건문으로 hasFocus인지 아닌지 꼭 검사를 해줘야 한다. 리스너가 불렸다고 무조건 라디오버튼에 체크하게 되면 심히 곤란한 상황이 연출될 수 있다. 왜 그런지 궁금하면 로그를 찍어보면 알 수 있다.
물론 궁금하지 않다면 그냥 넘어가도 무방하다.
val radioButtonListener = OnFocusChangeListener { v, hasFocus -> Log.d(TAG, "RadioButtonListener") if (hasFocus) { Log.d(TAG, "hasFocus true") // (v as RadioButton).isChecked = true } else { Log.d(TAG, "hasFocus false") }
위는 로그 예시. 로그를 찍는 방법을 잘 모르면 Toast메시지를 띄워도 되고 마음대로 하면 된다.
이렇게 하면 (로그 부분은 제외해도 무방함) 글의 맨 위에 있는 동영상처럼 작동한다.
끝