基础知识
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;
@Override
protected 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() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
// 键盘配置发生变化时重新处理
handleKeyboardState();
}
}
}, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
}
@Override
protected void onDestroy() {
super.onDestroy();
// 记得注销广播接收器
}
}
3. 在布局文件中配置
<EditText
android: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() {
@Override
public 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() {
@Override
public void onExternalKeyboardConnected() {
// 外接键盘连接时的处理
KeyboardManager.hideSoftKeyboard(MainActivity.this, editText);
Toast.makeText(MainActivity.this, "外接键盘已连接", Toast.LENGTH_SHORT).show();
}
@Override
public void onExternalKeyboardDisconnected() {
// 外接键盘断开时的处理
Toast.makeText(MainActivity.this, "外接键盘已断开", Toast.LENGTH_SHORT).show();
}
});
keyboardStateManager.startMonitoring();
主要特点:
- 自动检测:通过 Configuration 和 InputDevice 检测键盘状态
- 实时响应:监听配置变化和USB设备连接/断开
- 智能切换:根据键盘状态自动显示/隐藏软键盘
- 用户体验:提供适当的提示和反馈
这样实现后,你的应用就能智能地在物理键盘和软键盘之间切换了!