Fix navigating to action bar buttons on API 28

Keyboard focus clusters prevent that from working, so
we simply remove all focus clusters.

While they are generally a good idea, focus clusters were created
with Chrome OS and it's keyboard-driven interface in mind - there is no
documented way to move focus between clusters using only IR remote.
As such, there are no negative consequences to disabling them on Android TV.
This commit is contained in:
Alexander-- 2020-03-14 13:22:02 +06:59
parent 9cb3cf250c
commit 512046e300
1 changed files with 42 additions and 0 deletions

View File

@ -27,6 +27,7 @@ import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@ -37,6 +38,7 @@ import android.view.ViewTreeObserver;
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.view.WindowCallbackWrapper;
import org.schabi.newpipe.R;
@ -212,6 +214,8 @@ public final class FocusOverlayView extends Drawable implements
ViewGroup decor = (ViewGroup) window.getDecorView();
decor.getOverlay().add(overlay);
fixFocusHierarchy(decor);
ViewTreeObserver observer = decor.getViewTreeObserver();
observer.addOnScrollChangedListener(overlay);
observer.addOnGlobalFocusChangeListener(overlay);
@ -245,4 +249,42 @@ public final class FocusOverlayView extends Drawable implements
animator.sendEmptyMessageDelayed(0, 100);
}
private static void fixFocusHierarchy(View decor) {
// During Android 8 development some dumb ass decided, that action bar has to be a keyboard focus cluster.
// Unfortunately, keyboard clusters do not work for primary auditory of key navigation Android TV users
// (Android TV remotes do not have keyboard META key for moving between clusters). We have to fix this
// unfortunate accident. While we are at it, let's deal with touchscreenBlocksFocus too.
if (Build.VERSION.SDK_INT < 26) {
return;
}
if (!(decor instanceof ViewGroup)) {
return;
}
clearFocusObstacles((ViewGroup) decor);
}
@RequiresApi(api = 26)
private static void clearFocusObstacles(ViewGroup viewGroup) {
viewGroup.setTouchscreenBlocksFocus(false);
if (viewGroup.isKeyboardNavigationCluster()) {
viewGroup.setKeyboardNavigationCluster(false);
return; // clusters aren't supposed to nest
}
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; ++i) {
View view = viewGroup.getChildAt(i);
if (view instanceof ViewGroup) {
clearFocusObstacles((ViewGroup) view);
}
}
}
}