別のコントロールにフォーカスを設定せずにフォーカスを削除する方法は?


93

UIは直感的に使いたいです。各画面は、自然で控えめに、ユーザーをアプリの次のステップに案内する必要があります。それを除いて、私は物事をできるだけ混乱させ、混乱させるよう努めています。

冗談だ :-)

私には3つTableRowのがあり、それぞれに読み取り専用でフォーカスできないEditTextコントロールと、その右側にあるボタンが含まれています。各ボタンは同じアクティビティを開始しますが、引数は異なります。ユーザーがそこで選択を行うと、サブアクティビティが終了EditTextし、ユーザーの選択が適切なものに入力されます。

これは、古典的なカスケード値メカニズムです。各選択により、次の選択で使用可能なオプションが絞り込まれます。したがって、現在の行のEditTextに値が含まれるまで、次の各行の両方のコントロールを無効にします。

次の優先順位で、2つのことのいずれかを行う必要があります。

  1. ボタンがクリックされたら、別のボタンにフォーカスを設定せずに、すぐにフォーカスを削除します
  2. アクティビティの開始時に最初のボタンにフォーカスを設定します

問題はサブアクティビティが戻った後に現れます。クリックされたボタンはフォーカスを保持します。

再:上記の#1- removeFocus()メソッド、または類似したものがないようです

再:上記の#2- requestFocus()次の行のボタンにフォーカスを設定するために使用できます。これはサブアクティビティが戻った後に機能しますが、何らかの理由で親アクティビティので機能しませんonCreate()

どちらの方向にもUIの一貫性が必要です。サブアクティビティが終了した後にボタンにフォーカスがないか、ロジックフロー内の場所に応じて各ボタンがフォーカスを受け取ります(選択前の最初の(そして唯一の)アクティブなボタンを含む)。

回答:


173

clearFocus()の使用は、あなたが見つけたように(別の回答へのコメントで見たように)機能していないように思われましたが、結局私のために機能したのは、

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

私の最上位のレイアウトビュー(線形レイアウト)に。すべてのボタン/編集テキストなどからフォーカスを削除するには、次のようにします

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

ビューをフォーカス可能に設定しない限り、フォーカスを要求しても何も起こりませんでした。


一時的な瞬間のために、これはうまくいくかもしれないと思いました。「そのシンプルさでなんて美しいのだろう!」私は自分に言いました。悲しいかな、そうではなかった。requestFocus()を削除しても、次の行のボタンがフォーカスされます。これは2番目の設定としては問題ありませんが、onCreate()の最初のボタンに何らかの方法でフォーカスを設定できる場合のみです。
InteXX、

@InteXX:私は今日この問題に再び遭遇し、解決策を見つけました。あなたは今、別のルートを下ったことを知っていますが、同じ船に再び出会った場合は、これを試してみてください!
アクションエビ

「別の経路をたどってきたと思います」バックアップするのにまだ手遅れではありません:-)私はそれを試してあなたに知らせます、ありがとう。
InteXX、2011年

くそー。ほぼ、しかし完全ではありません。はい、最後にクリックしたボタンからフォーカスを外しますが、どのボタンもフォーカスを取得できなくなります。これは、私の非タッチユーザーがボタンをクリックできないことを意味します。同じことをしていますか?
InteXX、2011年

6
これはScrollViewでは機能しません。トップビューがScrollViewの場合、これを子で使用します。
ウロスPodkrižnik

79

古い質問ですが、同様の問題があり、結局何をしているかを共有したいと思ったときに出会いました。

フォーカスを得るビューは毎回異なるため、非常に一般的なものを使用しました:

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

12
これを行うエレガントな方法。clearFocus()を呼び出す前にgetCurrentFocus()からのnull値をチェックすることをお勧めします
Vering

4
+1はい、そのnullチェックを投入する必要があります!-なぜJavaはセーフトラバーサル演算子を実装できないのですか?それはのようにシンプルgetCurrentFocus()?.clearFocus();でとても素晴らしくエレガントです:-/
Levite

1
@willlma:はい、これはまさに私が意図したことでした。
Vering

5
@Levit非常にスウィフトのような。:-)しかし、Javaがそのような演算子を実装したとしても、Androidが追いつくまでに4年かかります。
グレッグブラウン

2
@Levit、おそらくあなたは今ではそれを見つけたでしょうが、Kotlin。
prodaea

9
  1. 使用できますView.clearFocus()

  2. View.requestFocus()から呼び出されonResume()た使用。


@siliconeagle:これは非常に奇妙です。(clearFocus()へのポインターのおかげで、btw-私はこれに気づきませんでした。)最初のボタンをクリックして選択してから戻ると、最初のボタンはフォーカスを受け取ることができません。私のコードでは、このボタンにフォーカス可能を設定していません。コードをお見せしたいのですが、この編集ウィンドウで使用できる文字が足りないため、コードを投稿するためだけに別の回答を入力する必要があるかどうかわかりません。
InteXX '25年

@siliconeagle:残念ながら、clearFocus()は機能しません。サブアクティビティが戻ると、ボタンはフォーカスを保持します。
InteXX、2011年

@siliconeagle:OK、最初のコメントは気にしないでください。ボタンのクリックイベントでsetFocusable(false)を使用していて、サブアクティビティが返された後に再度オンにするのを忘れていました。ただし、clearFocus()はまだ効果がありません-なぜでしょうか?onActivityResult()からすべてのボタンで呼び出していますが、クリックされたボタンはフォーカスを保持しています。奇数。
InteXX、2011年

@siliconeagle:@actionshrimp:フォーカスに関連するすべてのコマンドと設定を廃止することにしました。私の当初の目的は、無効にされたボタンに焦点を当てることを防ぐことでしたが、これがコストのかかるものである場合、それは価値がありません。requestFocus()、clearFocus()、またはsetFocusable()がない場合、サブアクティビティが戻った後、ボタンはフォーカスを保持しません。2つのゾウムシのうちの小さい方です。つまり、ユーザーが無効なボタンにフォーカスを設定できるようにする必要があります。
InteXX、2011年

無効化された要素はフォーカス可能ではありませんAFAIK ... setEnabled(false)を使用してください
シリコン

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について

もう1つ注意すべき点があります。デフォルトでは、Androidは最初のフォーカスをアクティビティの最初のEditTextまたはフォーカス可能なコントロールに自動的に割り当てます。当然、InputMethod(通常はソフトキーボード)は、それ自体を表示することによってフォーカスイベントに応答します。AndroidManifest.xmlのwindowSoftInputMode属性は、stateAlwaysHiddenに設定されている場合、この自動的に割り当てられた初期フォーカスを無視するようにキーボードに指示します。

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

素晴らしいリファレンス


5
<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に移動し、焦点を合わせ、focusabletrueとfocusableInTuchtrueに設定する平面図を見つけます。
  6. これの中にonResume()上の平面図を見つけますfindViewById
  7. 最後にこのonResume()セットの中requestFocus()をこのビューに。
  8. そして今お楽しみください......

2

ビューのフォーカス機能を無効にして有効にしようとしたところ、うまくいきました(フォーカスがリセットされました)。

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

1

メインアクティビティの状態を保存する機能をオフにしてみてください(そのため、どのコントロールにテキストがあり、何にフォーカスがあったかを忘れてしまいます)。EditTextの内容を記憶し、それらをonResume()に再入力する別の方法が必要です。startActivityForResult()を使用してサブアクティビティを起動し、メインアクティビティ内にonActivityResult()ハンドラを作成して、EditTextを正しく更新します。このように、myButton.post(new Runnable(){run(){myButton.requestFocus();}});を使用してEditTextに再入力すると同時に、フォーカスしたい適切なボタンを設定することができます。

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.