Skip to content

Android - TalkBack Barrierefreiheit Fokus auf eine bestimmte Ansicht setzen

Sie müssen nicht mehr im ganzen Internet suchen, weil Sie an der richtigen Stelle sind, wir haben die Antwort, die Sie benötigen, aber ohne Probleme.

Lösung:

DISCLAIMER: Erzwingen Fokus auf Aktivität laden, um irgendwo anders als an der oberen Leiste ist immer (okay, immer sollte fast nie gesagt werden), aber wirklich, tun Sie es einfach nicht. Es ist ein Verstoß gegen alle möglichen WCAG 2.0 Vorschriften, einschließlich 3.2.1 und 3.2.3, in Bezug auf vorhersehbare Navigation bzw. Kontextwechsel. Wahrscheinlich machen Sie Ihre App dadurch sogar noch unzugänglicher.

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

ENDE DES HAFTUNGSAUSSCHLUSSES.

Sie verwenden die richtigen Funktionsaufrufe. Alles, was Sie tun müssen, ist dies:

myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);

Das Problem ist eher der Zeitpunkt, an dem Sie versuchen, dies zu tun. Talkback verbindet sich mit Ihrer Aktivität etwas später im Aktivitätszyklus. Die folgende Lösung veranschaulicht dieses Problem. Ich bin mir nicht sicher, ob es einen besseren Weg gibt, dies zu tun, um ehrlich zu sein. Ich habe es mit onPostResume versucht, dem letzten Callback, den das Android-Betriebssystem in Bezug auf das Laden von Aktivitäten aufruft, und musste trotzdem eine Verzögerung einfügen.

@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);

}

Vielleicht können Sie eine benutzerdefinierte Ansicht erstellen. Die Rückrufe innerhalb der Ansicht können die Logik bieten, die Sie benötigen, um dies zu tun, ohne die Race Condition! Wenn ich Zeit habe, werde ich mir das später genauer ansehen.

Ich hatte das gleiche Problem, denn für eine konsistente Navigation sollte der Titel der neu geöffneten Seite ausgewählt werden.
Das Problem war, dass der Screenreader die erste Kopfzeile oben links auf meinen Seiten auswählte und nicht den Titel.

Ich hatte eine myRootView Variable für die gesamte Ansicht und eine myTitleView Variable für die Titeltextansicht.

Die Lösung, die ChrisCM vorgeschlagen hat, um die Barrierefreiheit auf die richtige Ansicht zu konzentrieren, hat mir auf jeden Fall geholfen:

myTitleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);

Allerdings hatte ich immer noch das Problem, dass der Aufruf dieses Codes beim Start der App keine Wirkung hatte, weil der Screenreader noch nicht bereit war, und die vorgeschlagene Lösung für "Warten, bis Talkback verfügbar ist", nämlich 5 volle Sekunden zu warten, war nichts, was ich tun wollte, weil der Benutzer in dieser Zeit vielleicht schon die Oberfläche benutzt und seine Auswahl durch den automatischen Fokus unterbrochen würde.

Mir ist aufgefallen, dass beim Öffnen der App systematisch die linke obere Kopfzeile durch die Barrierefreiheit ausgewählt wurde, also habe ich eine Klasse geschrieben, die auf diese Auswahl hört und direkt danach meine eigene Auswahl auslöst.

Hier ist der Code der fraglichen Klasse:

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);
    }
}

Dann verwende ich den Code wie folgt (zum Beispiel in der onPostResume-Methode der Activity):

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

Ich habe ein paar Stunden gebraucht, um herauszufinden, wie ich den Fokus sofort auf die richtige Ansicht bekomme, ich hoffe, das hilft auch anderen!

Vor kurzem hatte ich das gleiche Problem. Ich erstellte eine Android-Erweiterungsfunktion, um eine Ansicht zu fokussieren, die nicht fokussiert war, mit einer postDelayed wie die obige Lösunge;

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)

Aber ich hatte ein anderes Szenario, in dem es nicht funktionierte. Allerdings habe ich es mit diesem zu arbeiten:

fun View.accessibilityFocus(): View {
    this.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
    this.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)
    return this
}

Wenn Sie diesen Artikel nützlich fanden, wäre es sehr hilfreich, wenn Sie ihn auf diese Weise mit mehr Programmierern teilen, um unsere Informationen zu verbreiten.



Nutzen Sie unsere Suchmaschine

Suche
Generic filters

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.