다른 컨트롤에 포커스를 설정하지 않고 포커스를 제거하는 방법은 무엇입니까?


95

UI가 직관적 인 것이 좋습니다. 각 화면은 자연스럽게 앱의 다음 단계로 사용자를 안내해야합니다. 그것을 제외하고는 가능한 한 혼란스럽고 혼란스럽게 만들기 위해 노력합니다.

농담이야 :-)

TableRow각각 읽기 전용 및 포커스 불가능 EditText 컨트롤과 오른쪽에 버튼이 포함 된 세 개의 s가 있습니다. 각 버튼은 동일한 활동을 시작하지만 다른 인수를 사용합니다. 사용자가 거기에서 선택하고 하위 활동이 완료 EditText되어 사용자의 선택으로 해당 항목이 채워집니다.

이것은 고전적인 계단식 값 메커니즘입니다. 각 선택은 다음 선택 등에 사용할 수있는 옵션을 좁 힙니다. 따라서 현재 행의 EditText에 값이 포함될 때까지 다음 각 행에서 두 컨트롤을 모두 비활성화합니다.

이 선호도 순서로 두 가지 중 하나를 수행해야합니다.

  1. 버튼을 클릭하면 다른 버튼에 포커스를 설정하지 않고 즉시 포커스를 제거합니다.
  2. 활동이 시작될 때 첫 번째 버튼에 초점 설정

문제는 하위 활동이 반환 된 후에 나타납니다. 클릭 한 버튼은 포커스를 유지합니다.

Re : 위의 # 1- removeFocus()방법이나 비슷한 것이없는 것 같습니다.

다시 : # 2 위- requestFocus()다음 행의 버튼에 포커스를 설정하는 데 사용할 수 있으며 하위 활동이 반환 된 후에 작동하지만 어떤 이유로 부모 활동의 onCreate().

어느 방향 으로든 UI 일관성이 필요합니다. 하위 활동이 완료된 후 버튼에 포커스가 없거나 각 버튼은 선택 전의 첫 번째 (유일한) 활성 버튼을 포함하여 논리 흐름의 위치에 따라 포커스를받습니다.

답변:


173

clearFocus () 사용은 당신이 찾은 것처럼 (다른 답변에 대한 주석에서 본) 나에게도 효과가 없었지만 결국 나를 위해 일한 것은 다음과 같습니다.

<LinearLayout 
    android:id="@+id/my_layout" 
    android:focusable="true" 
    android:focusableInTouchMode="true" ...>

내 최상위 레이아웃보기 (선형 레이아웃)에. 모든 Buttons / EditTexts 등에서 포커스를 제거하려면 다음을 수행하십시오.

LinearLayout myLayout = (LinearLayout) activity.findViewById(R.id.my_layout);
myLayout.requestFocus();

초점을 맞출 수 있도록 뷰를 설정하지 않는 한 초점을 요청하는 것은 아무것도하지 않았습니다.


잠시 동안 나는 이것이 효과가있을 것이라고 생각했다. "단순함이 얼마나 아름다운가!" 나는 나 자신에게 말했다. 아아, 그렇지 않았습니다. requestFocus ()를 제거해도 다음 행의 버튼에 초점이 맞춰집니다. 이것은 두 번째 환경 설정으로 괜찮지 만 어떻게 든 onCreate ()의 첫 번째 버튼에 초점을 맞출 수있는 경우에만 가능합니다.
InteXX

@InteXX : 오늘 다시이 문제를 발견하고 해결책을 찾았습니다. 나는 당신이 지금 다른 길을 갔다는 것을 알고 있지만, 같은 배에서 다시 자신을 발견하면 이것을 시도하십시오!
actionshrimp

"당신이 지금 다른 길을 갔다는 것을 알아요"아직 백업하기에 너무 늦지 않았습니다. :-) 나는 그것을 시도하고 알려줄 것입니다. 감사합니다.
InteXX

꿰매다. 거의하지만 정답은 아닙니다. 예, 마지막으로 클릭 한 버튼에서 포커스를 떼지 만 모든 버튼이 포커스를 얻지 못하도록합니다. 이것은 내 비 터치 사용자가 버튼을 클릭 할 수 없음을 의미합니다. 당신에게도 똑같이하고 있습니까?
InteXX 2011 년

6
이것은 ScrollView에서 작동하지 않습니다. 상위 뷰가 ScrollView 인 경우 자식에서 사용합니다.
Uroš Podkrižnik 2011

79

오래된 질문이지만 비슷한 문제가 생겼을 때 내가 한 일을 공유 할 것이라고 생각했습니다.

초점을 맞춘 관점은 매번 달라서 매우 일반적인 것을 사용했습니다.

View current = getCurrentFocus();
if (current != null) current.clearFocus();

12
이것을하는 우아한 방법. clearFocus ()를 호출하기 전에 getCurrentFocus ()에서 null 값을 확인하고 싶을 수 있습니다.
Vering

4
+1 예, 그 널 체크를 던져야합니다! -Java가 안전한 순회 연산자를 구현할 수없는 이유는 무엇입니까? 그것은 단순하게 될 것이다 getCurrentFocus()?.clearFocus();, 그래서 좋은 우아한 : - /
레위

1
@willlma : 예, 이것이 정확히 제가 의미하는 바였습니다.
Vering

5
@Levit 매우 Swift와 같습니다. :-)하지만 자바가 그러한 연산자를 구현했다고해도 Android가 따라 잡기까지 4 년이 걸립니다.
Greg Brown

2
@Levit, 아마도 지금 쯤 발견했을 것입니다.하지만 Kotlin.
prodaea

9
  1. 사용할 수 있습니다 View.clearFocus().

  2. View.requestFocus()에서 호출 된 사용 onResume().


@siliconeagle : 이제 이것은 매우 이상합니다. (clearFocus () btw에 대한 포인터를 주셔서 감사합니다. 저는이 사실을 몰랐습니다.) 첫 번째 버튼을 클릭하고 선택을 한 다음 돌아 왔을 때 첫 번째 버튼은 더 이상 포커스를받을 수 없습니다. 내 코드의 어느 곳에서도이 버튼에 대해 포커스 가능을 설정하지 않습니다. 내 코드를 보여 드리고 싶지만이 편집 창에 사용할 수있는 문자가 충분하지 않아 처음 사용하기 때문에 코드를 게시 할 수 있도록 다른 답변을 입력해야하는지 잘 모르겠습니다.
InteXX

@siliconeagle : 안타깝게도 clearFocus ()는 작동하지 않습니다. 버튼은 하위 활동이 반환 될 때 포커스를 유지합니다.
InteXX

@siliconeagle : 좋아요, 첫 번째 댓글은 신경 쓰지 마세요. 버튼의 클릭 이벤트에서 setFocusable (false)을 사용하고 있었고 하위 활동이 반환 된 후 다시 켜는 것을 잊었습니다. clearFocus ()는 여전히 효과가 없습니다. 이유가 궁금합니다. onActivityResult ()의 모든 버튼에서 호출하고 있지만 클릭 한 버튼은 여전히 ​​포커스를 유지합니다. 이상한.
InteXX

@siliconeagle : @actionshrimp : 포커스 관련 명령과 설정을 모두 없애기로 결정했습니다. 나의 원래 의도는 비활성화 된 버튼에 초점을 맞추는 것을 막는 것이었지만 이것이 비용이 든다면 그만한 가치가 없습니다. requestFocus (), clearFocus () 또는 setFocusable ()이 없으면 하위 활동이 반환 된 후에도 버튼이 포커스를 유지하지 않습니다. 두 마리의 바구미 중 작은 것입니다. 사용자가 비활성화 된 버튼에 포커스를 설정할 수있는 상태에서 살아야 할 것 같습니다.
InteXX

비활성화 된 요소는 초점을 맞출 수 없습니다 AFAIK ... use setEnabled (false)
siliconeagle

8

android:descendantFocusability="beforeDescendants"

아래의 일부 레이아웃 옵션과 함께 활동에서 다음을 사용하면 원하는대로 작동하는 것 같습니다.

 getWindow().getDecorView().findViewById(android.R.id.content).clearFocus();

루트보기에서 다음 매개 변수와 관련하여.

<?xml
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:descendantFocusability="beforeDescendants" />

https://developer.android.com/reference/android/view/ViewGroup#attr_android:descendantFocusability

답변 : https://forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text

windowSoftInputMode 정보

알아야 할 또 다른 논쟁 점이 ​​있습니다. 기본적으로 Android는 활동의 첫 번째 EditText 또는 포커스 가능한 컨트롤에 초기 포커스를 자동으로 할당합니다. 당연히 InputMethod (일반적으로 소프트 키보드)가 자신을 표시하여 포커스 이벤트에 응답합니다. AndroidManifest.xml의 windowSoftInputMode 속성은 stateAlwaysHidden으로 설정 될 때 자동으로 할당 된 초기 포커스를 무시하도록 키보드에 지시합니다.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

훌륭한 참조


6
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:id="@+id/ll_root_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

LinearLayout llRootView = findViewBindId(R.id.ll_root_view);
llRootView.clearFocus();

이미 프로필 정보 업데이트를 완료하고 레이아웃의 EditText에서 모든 포커스를 제거 할 때 이것을 사용합니다.

====> 업데이트 : 상위 레이아웃 콘텐츠에서 내 EditText 추가 줄 :

android:focusableInTouchMode="true"


2

우선 100 % 작동합니다 ........

  1. onResume()메서드를 만듭니다 .
  2. 이 내부 onResume()에서 또 다시 초점을 맞추고보기를 찾을 수 있습니다 findViewById().
  3. 이보기 에이 onResume()세트 내부 requestFocus().
  4. 이보기 에이 onResume()세트 내부 clearFocus.
  5. 동일한 레이아웃의 xml로 이동하여 초점을 맞추고 싶은 상위 뷰를 찾고 focusable사실과 focusableInTuch사실로 설정하십시오 .
  6. 이 내부 onResume()에서 위의 평면도를 찾으십시오.findViewById
  7. 이 내부 onResume()세트 requestFocus()마지막에서이보기에.
  8. 그리고 이제 즐기세요 ...

2

보기에 대한 초점 기능을 비활성화하고 활성화하려고 시도했지만 저에게 효과적이었습니다 (초점이 재설정되었습니다).

focusedView.setFocusable(false);
focusedView.setFocusableInTouchMode(false);
focusedView.setFocusable(true);
focusedView.setFocusableInTouchMode(true);

1

상태를 저장하는 기본 활동의 기능을 해제 할 수 있습니다 (따라서 컨트롤에 텍스트가있는 것과 포커스가있는 것을 잊어 버림). EditText의 내용을 기억하고 onResume ()을 다시 채우는 다른 방법이 필요합니다. startActivityForResult ()로 하위 활동을 시작하고 EditText를 올바르게 업데이트하는 기본 활동에 onActivityResult () 핸들러를 만듭니다. 이런 식으로 myButton.post (new Runnable () {run () {myButton.requestFocus ();}});를 사용하여 EditText를 다시 채우는 동시에 Resume ()에 초점을 맞추고 싶은 적절한 버튼을 설정할 수 있습니다.

View.post () 메서드는 초기에 포커스를 설정하는 데 유용합니다. 그 런너 블은 창이 생성되고 상황이 안정된 후에 실행되어 해당 시간까지 포커스 메커니즘이 제대로 작동 할 수 있기 때문입니다. onCreate / Start / Resume () 중에 포커스를 설정하려고하면 일반적으로 문제가 발생합니다.

이것은 의사 코드이며 테스트되지 않았지만 시도 할 수있는 가능한 방향입니다.


두 번째 생각에 ... 활동의 저장된 상태를 끄는 대신 View.post () 항목을 먼저 사용하십시오. 그것은 그 자체로 당신을 위해 트릭을 할 수 있습니다.
삼촌 코드 원숭이

아아, 더 이상 우리를 위해 이것을 테스트하는 쉬운 방법이 없습니다. 그 이후로 네이티브 코드 모델을 버리고 모바일 앱용 HTML5 / CSS3를 사용하기로 결정했으며 그에 따라 시스템을 재구성했습니다. 그러나 매우 깊이있는 답변으로 보이는 것에 감사드립니다. 나는 그것을 투표했다.
InteXX 2011 년

1
android:focusableInTouchMode="true"
android:focusable="true"
android:clickable="true"

EditTextView를 포함하는 ViewGroup에 추가하십시오. 내 제약 레이아웃에 제대로 작동합니다. 이 도움을 바랍니다


0

다음 시도 (전화 걸기 clearAllEditTextFocuses();)

private final boolean clearAllEditTextFocuses() {
    View v = getCurrentFocus();
    if(v instanceof EditText) {
        final FocusedEditTextItems list = new FocusedEditTextItems();
        list.addAndClearFocus((EditText) v);

        //Focus von allen EditTexten entfernen
        boolean repeat = true;
        do {
            v = getCurrentFocus();
            if(v instanceof EditText) {
                if(list.containsView(v))
                    repeat = false;
                else list.addAndClearFocus((EditText) v);
            } else repeat = false;
        } while(repeat);

        final boolean result = !(v instanceof EditText);
        //Focus wieder setzen
        list.reset();
        return result;
    } else return false;
}

private final static class FocusedEditTextItem {

    private final boolean focusable;

    private final boolean focusableInTouchMode;

    @NonNull
    private final EditText editText;

    private FocusedEditTextItem(final @NonNull EditText v) {
        editText = v;
        focusable = v.isFocusable();
        focusableInTouchMode = v.isFocusableInTouchMode();
    }

    private final void clearFocus() {
        if(focusable)
            editText.setFocusable(false);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(false);
        editText.clearFocus();
    }

    private final void reset() {
        if(focusable)
            editText.setFocusable(true);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(true);
    }

}

private final static class FocusedEditTextItems extends ArrayList<FocusedEditTextItem> {

    private final void addAndClearFocus(final @NonNull EditText v) {
        final FocusedEditTextItem item = new FocusedEditTextItem(v);
        add(item);
        item.clearFocus();
    }

    private final boolean containsView(final @NonNull View v) {
        boolean result = false;
        for(FocusedEditTextItem item: this) {
            if(item.editText == v) {
                result = true;
                break;
            }
        }
        return result;
    }

    private final void reset() {
        for(FocusedEditTextItem item: this)
            item.reset();
    }

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.