50

TalkBack が有効になっている場合、アクセシビリティ フォーカス マニュアルを特定のビューに設定する方法はありますか? たとえば、アクティビティが開始されたときに、TalkBack が自動的に特定のボタン (ビューの周りの黄色のフレーム) にフォーカスし、そのコンテンツの説明を読み上げるようにします。

私がこれまでに試したこと:

    myButton.setFocusable(true);
    myButton.setFocusableInTouchMode(true);
    myButton.requestFocus();

requestFocus() は、入力フォーカスのみを要求しているようで、アクセシビリティ フォーカスとは何の関係もありません。私も試しました:

    myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
    myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
    myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
    myButton.announceForAccessibility("accessibility test");
    myButton.performAccessibilityAction(64, null); // Equivalent to ACTION_ACCESSIBILITY_FOCUS

    AccessibilityManager manager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
    if (manager.isEnabled()) {
        AccessibilityEvent e = AccessibilityEvent.obtain();
        e.setSource(myButton);
        e.setEventType(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
        e.setClassName(getClass().getName());
        e.setPackageName(getPackageName());
        e.getText().add("another accessibility test");
        manager.sendAccessibilityEvent(e);
    }

これはどれもうまくいかないようです。

4

5 に答える 5

63

免責事項: アクティビティの負荷をトップ バー以外の場所に強制的に配置することは常に行われますが (ほとんど常に言われることはありません)、実際には、そうしないでください。これは、予測可能なナビゲーションとコンテキストの変更に関するそれぞれ 3.2.1 と 3.2.3 を含む、あらゆる種類の WCAG 2.0 規則に違反しています。おそらく、これを行うことで、実際にアプリにアクセスできなくなります。

http://www.w3.org/TR/WCAG20/#consistent-behavior

免責事項を終了します。

正しい関数呼び出しを使用しています。あなたがする必要があるのはこれだけです:

myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);

問題は、これを実行しようとした時点にある可能性が高くなります。Talkback は、アクティビティ サイクルの少し後にアクティビティに接続されます。次の解決策はこの問題を示しています。正直に言うと、これより良い方法があるかどうかはわかりません。アクティビティの読み込みに関して、Android OS が呼び出す最後のコールバックである onPostResume を試しましたが、遅延を追加する必要がありました。

@Override
protected void onPostResume() {
    super.onPostResume();

    Log.wtf(this.getClass().getSimpleName(), "onPostResume");

    Runnable task = new Runnable() {

        @Override
        public void run() {
            Button theButton = (Button)WelcomeScreen.this.findViewById(R.id.idButton);
            theButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        }
    };

    final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();

    worker.schedule(task, 5, TimeUnit.SECONDS);

}

カスタム ビューを作成できる場合があります。ビュー内のコールバックは、競合状態なしで、これを行うために必要なロジックを提供する場合があります! 時間があれば後で詳しく調べるかもしれません。

于 2015-02-12T15:15:26.670 に答える
12

最近、私は同じ問題を抱えていました。postDelayed提案された他のソリューションのようにフォーカスされていないビューにフォーカスする Android 拡張機能を作成しました。

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)

しかし、それが機能しない別のシナリオがありました。ただし、これで動作するようになりました:

fun View.accessibilityFocus(): View {
    this.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
    this.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)
    return this
}
于 2020-10-29T18:55:50.373 に答える
8

一貫したナビゲーションのために、新しく開いたページのタイトルを選択したかったので、同じ問題がありました。問題は、スクリーン リーダーがタイトルではなく、ページの左上にある最初のヘッダー ボタンを選択していたことです。

myRootViewビュー全体の変数myTitleViewと、タイトル テキスト ビューの変数がありました。

アクセシビリティを適切なビューに集中させるために ChrisCM が提案したソリューションは、間違いなく私を助けてくれました。

myTitleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);

ただし、アプリの起動時にこのコードを呼び出しても効果がないという問題がまだありました。これは、スクリーン リーダーがまだ準備できていなかったためです。また、5 秒間待機するという「トークバックが利用可能になるのを待つ」ために提案された解決策は、私がやりたいことではありませんでした。それまでに、ユーザーはすでにインターフェイスを使用している可能性があり、その選択は自動フォーカスによって中断されるためです。

アプリを開くと、左上のヘッダー ボタンがアクセシビリティによって体系的に選択されていることに気付きました。そのため、その選択をリッスンし、その直後に独自の選択をトリガーするクラスを作成しました。

問題のクラスのコードは次のとおりです。

import android.view.View;
import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public abstract class OnFirstAccessibilityFocusRunner extends AccessibilityDelegate implements Runnable {
    @NonNull
    private final View rootView;
    private boolean hasAlreadyRun = false;

    public OnFirstAccessibilityFocusRunner(@NonNull final View _rootView) {
        rootView = _rootView;
        init();
    }

    private void init() {
        rootView.setAccessibilityDelegate(this);
    }

    @Override
    public boolean onRequestSendAccessibilityEvent(@Nullable final ViewGroup host, @Nullable final View child,
        @Nullable final AccessibilityEvent event) {
        if (!hasAlreadyRun
            && event != null
            && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
        ) {
            hasAlreadyRun = true;
            rootView.setAccessibilityDelegate(null);
            run();
        }
        return super.onRequestSendAccessibilityEvent(host, child, event);
    }
}

次に、次のようなコードを使用します (たとえば、アクティビティの onPostResume メソッド内)。

@Override
protected void onPostResume() {
    new OnFirstAccessibilityFocusRunner(myRootView) {
        @Override
        public void run() {
            myTitleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        }
    };
}

適切なビューにフォーカスを即座に合わせる方法を理解するのに数時間かかりました。これが他の人にも役立つことを願っています!

于 2020-01-20T22:40:55.620 に答える