Android 键盘
基础知识
1. 物理键盘(Physical Keyboard)
定义
物理键盘指的是设备上真实存在的、可以按压的键盘。例如:
- 早期的 Android 手机(如黑莓、摩托罗拉 Milestone)自带的 QWERTY 键盘
- 外接的蓝牙/USB 键盘
- 平板或 Chromebook 上的实体键盘
特点
- 输入响应快,无需屏幕空间
- 支持快捷键、组合键
- 适合大量文字输入或开发者使用
开发相关
- 可以通过 KeyEvent 监听物理键盘事件
- 物理键盘连接时,系统通常会自动隐藏软键盘
2. 软件盘(Soft Keyboard / 虚拟键盘)
定义
软件盘是指在屏幕上弹出的虚拟键盘。绝大多数 Android 设备都内置了软键盘(如 Gboard、百度输入法等)。
特点
- 触摸屏幕输入
- 可根据输入场景切换布局(数字、符号、表情等)
- 支持多语言、手写、语音输入等扩展功能
- 会占用部分屏幕空间
开发相关
- 通过 InputMethodManager 控制软键盘的显示与隐藏
- 可以在 EditText 上设置输入类型(如数字、密码等)
- 软键盘弹出时,可能会影响界面布局(如遮挡输入框),需要合理处理(如使用 android:windowSoftInputMode)
3. 物理键盘与软键盘的关系
- 如果设备连接了物理键盘,Android 系统通常会自动隐藏软键盘,除非用户手动调出。
- 开发者可以通过代码判断当前是否有物理键盘连接(如 Configuration.keyboard)。
- 某些场景下,开发者可以强制显示软键盘,即使有物理键盘。
4. 常见开发场景
- 监听键盘事件:通过 onKeyDown、onKeyUp 监听物理键盘输入。
- 软键盘控制:通过 InputMethodManager.showSoftInput() 和 hideSoftInputFromWindow() 控制软键盘。
- 适配键盘弹出:使用 android:windowSoftInputMode 控制界面适配。
5. 相关 API
- KeyEvent:物理键盘事件
- InputMethodManager:软键盘管理
- Configuration.keyboard:判断当前键盘类型
需求
一个需求,当连接外接键盘的时候,用外接,没有就用系统的。
Android 系统默认就会这样处理,但如果你需要更精确的控制,可以通过以下方式实现:
1. 检测键盘类型
首先需要检测当前是否有物理键盘连接:
public class KeyboardManager {/*** 检测是否有物理键盘连接*/public static boolean hasPhysicalKeyboard(Context context) {Configuration config = context.getResources().getConfiguration();return config.keyboard == Configuration.KEYBOARD_QWERTY ||config.keyboard == Configuration.KEYBOARD_12KEY;}/*** 检测是否有外接键盘*/public static boolean hasExternalKeyboard(Context context) {// 方法1:通过Configuration检测Configuration config = context.getResources().getConfiguration();boolean hasHardwareKeyboard = config.keyboard != Configuration.KEYBOARD_UNDEFINED;// 方法2:通过InputDevice检测(更精确)InputManager inputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);int[] deviceIds = inputManager.getInputDeviceIds();for (int deviceId : deviceIds) {InputDevice device = inputManager.getInputDevice(deviceId);if (device != null && device.isExternal()) {// 检查是否是键盘设备int sources = device.getSources();if ((sources & InputDevice.SOURCE_KEYBOARD) != 0) {return true;}}}return hasHardwareKeyboard;}/*** 根据键盘状态显示或隐藏软键盘*/public static void handleKeyboard(Context context, View view) {if (hasExternalKeyboard(context)) {// 有外接键盘时,隐藏软键盘hideSoftKeyboard(context, view);} else {// 没有外接键盘时,显示软键盘showSoftKeyboard(context, view);}}/*** 显示软键盘*/public static void showSoftKeyboard(Context context, View view) {InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);if (imm != null) {imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);}}/*** 隐藏软键盘*/public static void hideSoftKeyboard(Context context, View view) {InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);if (imm != null) {imm.hideSoftInputFromWindow(view.getWindowToken(), 0);}}
}
2. 在Activity中使用
public class MainActivity extends AppCompatActivity {private EditText editText;private KeyboardManager keyboardManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);editText = findViewById(R.id.edit_text);// 监听键盘状态变化registerKeyboardStateReceiver();// 初始处理键盘状态handleKeyboardState();}private void handleKeyboardState() {if (KeyboardManager.hasExternalKeyboard(this)) {// 有外接键盘时的处理editText.setHint("使用外接键盘输入");KeyboardManager.hideSoftKeyboard(this, editText);} else {// 没有外接键盘时的处理editText.setHint("点击输入");editText.setOnFocusChangeListener((v, hasFocus) -> {if (hasFocus) {KeyboardManager.showSoftKeyboard(this, editText);}});}}private void registerKeyboardStateReceiver() {// 注册配置变化监听器registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {// 键盘配置发生变化时重新处理handleKeyboardState();}}}, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));}@Overrideprotected void onDestroy() {super.onDestroy();// 记得注销广播接收器}
}
3. 在布局文件中配置
<EditTextandroid:id="@+id/edit_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="输入文字"android:inputType="text"android:windowSoftInputMode="adjustResize" />
4. 更高级的实现(监听键盘连接/断开)
public class KeyboardStateManager {private Context context;private OnKeyboardStateChangeListener listener;public interface OnKeyboardStateChangeListener {void onExternalKeyboardConnected();void onExternalKeyboardDisconnected();}public KeyboardStateManager(Context context, OnKeyboardStateChangeListener listener) {this.context = context;this.listener = listener;}public void startMonitoring() {// 监听USB设备连接IntentFilter usbFilter = new IntentFilter();usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);usbFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);context.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {// 检查是否是键盘设备UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (isKeyboardDevice(device)) {listener.onExternalKeyboardConnected();}} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (isKeyboardDevice(device)) {listener.onExternalKeyboardDisconnected();}}}}, usbFilter);}private boolean isKeyboardDevice(UsbDevice device) {if (device == null) return false;// 检查设备类是否为HID(Human Interface Device)return device.getDeviceClass() == UsbConstants.USB_CLASS_HID;}
}
5. 使用示例
// 在Activity中使用
KeyboardStateManager keyboardStateManager = new KeyboardStateManager(this, new KeyboardStateManager.OnKeyboardStateChangeListener() {@Overridepublic void onExternalKeyboardConnected() {// 外接键盘连接时的处理KeyboardManager.hideSoftKeyboard(MainActivity.this, editText);Toast.makeText(MainActivity.this, "外接键盘已连接", Toast.LENGTH_SHORT).show();}@Overridepublic void onExternalKeyboardDisconnected() {// 外接键盘断开时的处理Toast.makeText(MainActivity.this, "外接键盘已断开", Toast.LENGTH_SHORT).show();}
});keyboardStateManager.startMonitoring();
主要特点:
- 自动检测:通过 Configuration 和 InputDevice 检测键盘状态
- 实时响应:监听配置变化和USB设备连接/断开
- 智能切换:根据键盘状态自动显示/隐藏软键盘
- 用户体验:提供适当的提示和反馈
这样实现后,你的应用就能智能地在物理键盘和软键盘之间切换了!