Android TV 默认没有焦点

本文详细解析了Android设备开机后Launcher焦点缺失的问题,探讨了其背后的机制,即默认的TouchMode状态导致的焦点异常,并提供了具体的修改方法,包括在Launcher和ViewRootImpl中的代码调整,以确保开机时Launcher能正确获取焦点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

开机后Launcher默认无焦点,按键后焦点会出现,但不是在想要的位置上。

分析

Launcher.java中主动对指定View调用requestFocus()方法,重启后无法获取焦点,放在平时肯定是获取到焦点的。

试着Launcher.java拦截dispatchKeyEvent(),发现现象依然如此,因此判断开机后按键后的获取焦点并不在这里处理,这违背了之前所熟悉的焦点查找流程。

在ViewPostImeInputStage的processKeyEvent()方法没有处理,那应该是之前的InputStage处理了,于是打印线程调用栈

01-04 00:05:52.371  6046  6046 W System.err: 	at java.lang.Thread.dumpStack(Thread.java:1348)
01-04 00:05:52.371  6046  6046 W System.err: 	at android.view.FocusFinder.findNextFocusInAbsoluteDirection(FocusFinder.java:341)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.FocusFinder.findNextFocus(FocusFinder.java:269)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.FocusFinder.findNextFocus(FocusFinder.java:110)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.FocusFinder.findNextFocus(FocusFinder.java:80)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.focusSearch(ViewRootImpl.java:6428)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.leaveTouchMode(ViewRootImpl.java:4273)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.ensureTouchModeLocally(ViewRootImpl.java:4206)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.ensureTouchMode(ViewRootImpl.java:4188)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.checkForLeavingTouchModeAndConsume(ViewRootImpl.java:6076)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl.-wrap1(Unknown Source:0)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$EarlyPostImeInputStage.processKeyEvent(ViewRootImpl.java:4698)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$EarlyPostImeInputStage.onProcess(ViewRootImpl.java:4679)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4371)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4337)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4464)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4345)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4521)
01-04 00:05:52.372  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4371)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4337)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4345)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4371)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4337)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4464)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4345)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4521)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6922)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6896)
01-04 00:05:52.373  6046  6046 W System.err: 	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6853)

发现在EarlyPostImeInputStage阶段进行了一些处理,看调用栈里的方法就知道了原因,就是Android开机默认处于TouchMode,故即使requestFocus焦点也不会出现焦点,只有通过按键才可以退出TouchMode,那如何开机后进入到Launcher就有焦点存在,我的改法如下,如果有更好改法希望可以交流,谢谢!

解决

frameworks/base/core/java/android/view/ViewRootImpl.java

// 添加该方法调用原有逻辑退出TouchMode
/*
* @hide
*/
public void disableTouchMode() {
	ensureTouchMode(false);
}

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

// breeze begin
private boolean disableTouchMode;
// breeze end

public void finishBindingItems() {
    ...
    if (mLauncherCallbacks != null) {
        mLauncherCallbacks.finishBindingItems(false);
    }
    if (LauncherAppState.PROFILE_STARTUP) {
        Trace.endSection();
    }
    ...
	// breeze begin
	View view = getWindow().peekDecorView();
	if (view == null) {
		return;		
	}
	ViewRootImpl viewRootImpl = view.getViewRootImpl();
	if(viewRootImpl != null && !disableTouchMode) {
		Log.i("breeze","isInTouchMode , so disable it for myos");
		viewRootImpl.disableTouchMode();
		mAllAppsButton.requestFocus();
		disableTouchMode = true;
	}
	// breeze end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值