FSA全栈行动 FSA全栈行动
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr

公众号:FSA全栈行动

记录学习过程中的知识
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr
  • AndroidUI

  • Android第三方SDK

  • Android混淆

  • Android仓库

  • Android新闻

  • Android系统开发

  • Android源码

  • Android注解AOP

  • Android脚本

  • AndroidTv开发

    • AndroidTV - 获取Mac地址
    • AndroidTV - 解决EditText焦点无法转移问题
      • 一、源码分析
      • 二、自定义EditText
  • AndroidNDK

  • Android音视频

  • Android热修复

  • Android性能优化

  • Android云游戏

  • Android插件化

  • iOSUI

  • iOS工具

  • iOS底层原理与应用

  • iOS组件化

  • iOS音视频

  • iOS疑难杂症

  • iOS之Swift

  • iOS之RxSwift

  • iOS开源项目

  • iOS逆向

  • Flutter开发

  • 移动端
  • AndroidTv开发
GitLqr
2020-03-31
目录

AndroidTV - 解决EditText焦点无法转移问题

欢迎关注微信公众号:[FSA全栈行动 👋]

经反馈,在AndroidTV9.0 盒子上发现EditText一旦获取了焦点之后,遥控器上的方向键就无效了,即焦点无法再转移到其他焦点控件上,但这个问题在Android7.0及以下盒子上却不会出现,应该是Android8.0及以上源码做了修改,故查看EditText源码,得知确实是官方源码对方向键进行了处理~

# 一、源码分析

EditText源码中搜索onKeyDown,定位到父类TextView中的onKeyDown():

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    final int which = doKeyDown(keyCode, event, null);
    if (which == KEY_EVENT_NOT_HANDLED) {
        return super.onKeyDown(keyCode, event);
    }
    return true;
}

很明显doKeyDown()是关键方法,查看该方法的代码逻辑,主意看注释的部分。

大意:消费掉键盘的箭头事件以防止焦点离开。

private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
	...
	if (mMovement != null && mLayout != null) {
		...
		// Consume arrows from keyboard devices to prevent focus leaving the editor.
		// DPAD/JOY devices (Gamepads, TV remotes) often lack a TAB key so allow those
		// to move focus with arrows.
		if (event.getSource() == InputDevice.SOURCE_KEYBOARD
				&& isDirectionalNavigationKey(keyCode)) {
			return KEY_EVENT_HANDLED;
		}
	}

	return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode)
			? KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED;
}

private boolean isDirectionalNavigationKey(int keyCode) {
	switch(keyCode) {
		case KeyEvent.KEYCODE_DPAD_UP:
		case KeyEvent.KEYCODE_DPAD_DOWN:
		case KeyEvent.KEYCODE_DPAD_LEFT:
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			return true;
	}
	return false;
}

# 二、自定义EditText

通过上面的源码分析,明确原因之后,解决思路也就很明朗了,即:去掉对键盘方向事件的控制即可。但不管是doKeyDown()还是isDirectionalNavigationKey(),这些方法都是私有的,无法通过重写的方式来改变原有逻辑,能重写的只有onKeyDown(),所以,结合FocusFinder通过手动查找焦点控件的方式来处理就好了,完整代码如下:

/**
 * @author LQR
 * @time 2020/3/31
 * @desc 解决Android8.0 EditText获取焦点后,无法转换焦点问题
 */
@SuppressLint("AppCompatCustomView")
public class LQREditText extends EditText {
    public LQREditText(Context context) {
        super(context);
    }

    public LQREditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LQREditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public LQREditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (isDirectKeyCode(keyCode)) {
            int direction = FOCUS_DOWN;
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_UP:
                    direction = FOCUS_UP;
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    direction = FOCUS_DOWN;
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN_LEFT:
                    direction = FOCUS_LEFT;
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    direction = FOCUS_RIGHT;
                    break;
            }
            View nextFocus = FocusFinder.getInstance().findNextFocus((ViewGroup) getParent(), this, direction);
            if (nextFocus != null) {
                nextFocus.requestFocus();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    private boolean isDirectKeyCode(int keyCode) {
        return keyCode == KeyEvent.KEYCODE_DPAD_UP
                || keyCode == KeyEvent.KEYCODE_DPAD_DOWN
                || keyCode == KeyEvent.KEYCODE_DPAD_LEFT
                || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT;
    }
}

#AndroidTV#机顶盒#焦点
AndroidTV - 获取Mac地址
AndroidNDK - makefile语法详解

← AndroidTV - 获取Mac地址 AndroidNDK - makefile语法详解→

最近更新
01
Flutter - Xcode16 还原编译速度
04-05
02
AI - 免费的 Cursor 平替方案
03-30
03
Android - 2025年安卓真的闭源了吗
03-28
更多文章>
Theme by Vdoing | Copyright © 2020-2025 FSA全栈行动
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×