만족

[Android Studio] Focus 본문

[Android Studio] Focus

FrontEnd/Android Satisfaction 2017. 6. 30. 03:50

Focusable이 true로 되어 있는 뷰가 사용자와 Interaction하기 시작할 때, 그 뷰는 Focus를 가졌다 라고 한다.


대표적 예로는 EditText가 있으며, EditText를 누르면 키보드가 보여지면서 EditText와 상호작용할 수 있게 되는데, 

이 때 EditText는 Focus를 갖게 된다.


Focus를 갖기 위해, Focusable의 속성이 true이어야 하는데, EditText의 경우 별도의 작업이 필요 없이 true를 값으로 갖지만

TextView와 같은 태그들은 임의로 속성값을 바꾸어 주어야 한다.


Focusable 속성값 변경하기


​1. xml에서 변경하기


해당 태그에 

android:focusable="true"

android:focusableInTouchMode="true"

속성을 추가해주면 된다.


예시)



<LinearLayout
android:id="@+id/linearLayout_focus"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>

2. java에서 변경하기


해당 태그를 findViewById를 이용하여 찾은 다음


setFocusable(true), setFocusableInTouchMode(true)메소드를 이용한다.


예시)


b.setFocusable(true);
b.setFocusableInTouchMode(true);

Focusable과 FocusableInTouchMode의 차이점


Focusable은 단순히 해당 뷰가 Focus를 가질 수 있는지 없는지의 여부를 결정한다.


FocusableInTouchMode는 터치 모드에서, 즉 사용자의 터치에 의해서 포커스를 가질 수 있는지를 결정한다.


setFocusable Method (ref API)


Set whether this view can receive the focus. Setting this to false will also ensure that this view is not focusable in touch mode.

이 뷰가 포커스를 가질 수 있는지 없는지를 설정한다. 이것을 false로 설정하는 것은 터치 모드에서도 focus를 가질수 없음을 보장한다.


setFocusableInTouchMode (ref API)


Set whether this view can receive focus while in touch mode. Setting this to true will also ensure that this view is focusable.

이 뷰가 터치 모드에서 포커스를 받을 수 있는지를 설정한다. 이것을 true로 설정하는 것은 그 뷰가 focus를 가질 수 있음을 보장한다.


조금 더 자세한 설명은 Android Developers Blog를 참조하라.

https://android-developers.googleblog.com/2008/12/touch-mode.html


자동 포커싱


한 액티비티에서, Focusable한 뷰가 있다면 가장 첫 번째 Focusable View에게 Focus를 부여한다.

이는 의도치 않은 동작을 야기시킬수 있기 때문에 해당 행동을 의도하지 않았다면, 앞에 dummy Tag를 이용하여 포커싱을 막아야 한다.

예를 들어 다음의 코드에서
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.windows10.selectortag.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEXT"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input"
android:id="@+id/editText"
android:layout_centerInParent="true"
android:background="@drawable/ex_selector"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/editText"
android:id="@+id/btn"/>

</RelativeLayout>
EditText가 첫 번째 Focusable View 이므로, 해당 액티비티가 시작되면 자동으로 EditText를 포커싱한다.

이를 방지하기 위해, 맨 앞에 더미 태그를 다음과 같이 삽입한다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.windows10.selectortag.MainActivity">

<LinearLayout
android:id="@+id/linearLayout_focus"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEXT"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input"
android:id="@+id/editText"
android:layout_centerInParent="true"
android:background="@drawable/ex_selector"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/editText"
android:id="@+id/btn"/>

</RelativeLayout>

이렇게 하면, 가장 첫 번째 Focusable View가 LinearLayout이 되어, LinearLayout이 자동 포커싱 되게 된다.

그런데 한가지 궁금한 점은, 분명 더미 태그 삽입 전에는 EditText이 자동 포커싱 되므로, hasFocus의 결괏값이 true가 되어야 하는데
hasFocus의 결과는 false인데, 포커스는 가지고 있는 기현상이 발생한다...(?)

아직 이 문제의 해답은 찾지 못했는데, 찾으면 마저 추가하겠다.

FocusChangeEvent

Focus의 status가 바뀌는 Event를 인식하는 Listener가 있다.

onClickListener와 같은 방법으로 사용하면 된다.

예시)

textView.setOnFocusChangeListener(new View.OnFocusChangeListener(){
@Override
public void onFocusChange(View view, boolean b) {
//Variable 'b' represent whether this view has focus.
//If b is true, that means "This view is having focus"
textView.append("\nFocus: "+b);
}
});

OnFocusChangeListener는 인터페이스이므로 반드시 onFocusChange를 오버라이드 해야 한다.

두 번째 파라미터인 boolean b를 통해, focus의 상태를 알 수 있다.




Comments