ソースを参照

[fix]键盘引导页,处理登录弹窗显示时,让输入框失去焦点

hezihao 7 ヶ月 前
コミット
8828d9ef84

+ 11 - 2
lib/dialog/login/login_dialog.dart

@@ -3,8 +3,12 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:get/get.dart';
 import 'package:keyboard/dialog/login/login_dialog_controller.dart';
 import '../../module/login/login_controller.dart';
+import '../../utils/event_bus.dart';
 import 'login_dialog_view.dart';
 
+/// 登录弹窗显示事件
+const eventLoginDialogShow = "event_login_dialog_show";
+
 class LoginDialog {
   static const String TAG = "LoginDialog";
 
@@ -14,11 +18,16 @@ class LoginDialog {
       clickMaskDismiss: true,
       alignment: Alignment.bottomCenter,
       animationType: SmartAnimationType.centerScale_otherSlide,
-
       tag: TAG,
       keepSingle: true,
       onDismiss: () => Get.delete<LoginDialogController>(),
-      builder: (_) => const LoginDialogView(),
+      builder: (context) {
+        // 通知外部,登录弹窗显示
+        WidgetsBinding.instance.addPostFrameCallback((_) {
+          eventBus.post(eventLoginDialogShow);
+        });
+        return const LoginDialogView();
+      },
     );
   }
 }

+ 14 - 0
lib/module/keyboard_guide/keyboard_guide_controller.dart

@@ -5,8 +5,10 @@ import 'package:keyboard/module/keyboard_guide/enums/keyboard_guide_msg_type.dar
 import 'package:keyboard/resource/string.gen.dart';
 import '../../base/base_controller.dart';
 import '../../data/bean/keyboard_guide_msg.dart';
+import '../../dialog/login/login_dialog.dart';
 import '../../utils/clipboard_util.dart';
 import '../../utils/default_keyboard_helper.dart';
+import '../../utils/event_bus.dart';
 import '../../utils/floating_window_helper.dart';
 import '../../utils/keyboard_guide_record_util.dart';
 import '../../utils/keyboard_tutorial_util.dart';
@@ -44,6 +46,7 @@ class KeyboardGuidePageController extends BaseController {
   @override
   void onInit() {
     super.onInit();
+    eventBus.register(eventLoginDialogShow, _handleLoginDialogShow);
     inputFocusNode.addListener(_handleTextFieldFocusChange);
     // 初始化消息列表
     _initMsgList();
@@ -56,6 +59,7 @@ class KeyboardGuidePageController extends BaseController {
   @override
   void onClose() {
     // 取消监听
+    eventBus.unRegister(eventLoginDialogShow, _handleLoginDialogShow);
     inputFocusNode.removeListener(_handleTextFieldFocusChange);
     inputFocusNode.dispose();
     editingController.dispose();
@@ -63,6 +67,11 @@ class KeyboardGuidePageController extends BaseController {
     super.onClose();
   }
 
+  /// 登陆弹窗显示,让输入框失去焦点
+  void _handleLoginDialogShow(args) {
+    clearInputFocus();
+  }
+
   /// 手动将教程标志位,代表教程结束,因为有可能用户已经手动将所有设置都完成了
   /// 然后重装app,就会导致标志位没有机会设置为false,启动app时就回不断跳到这个页面
   void setNotFirstShowKeyboardTutorial() {
@@ -193,6 +202,11 @@ class KeyboardGuidePageController extends BaseController {
     inputFocusNode.requestFocus();
   }
 
+  /// 让输入框失去焦点
+  void clearInputFocus() {
+    inputFocusNode.unfocus();
+  }
+
   /// 显示引导覆盖层弹窗
   void showGuideOverlayDialog() {
     // 显示过引导弹窗,则不显示

+ 2 - 2
lib/module/keyboard_guide/keyboard_guide_page.dart

@@ -44,7 +44,6 @@ class KeyboardGuidePage extends BasePage<KeyboardGuidePageController> {
         onAppLifecycleCallback: (isForeground) {
           // 完成教程
           controller.setNotFirstShowKeyboardTutorial();
-
           if (isForeground) {
             // 切换到前台时,重新检查设置,更新按钮状态
             controller.checkSetting();
@@ -193,6 +192,7 @@ class KeyboardGuidePage extends BasePage<KeyboardGuidePageController> {
                       borderRadius: BorderRadius.circular(10.0),
                     ),
                     child: TextField(
+                      autofocus: false,
                       style: TextStyle(
                         color: ColorName.black80,
                         fontSize: 14.0,
@@ -217,7 +217,7 @@ class KeyboardGuidePage extends BasePage<KeyboardGuidePageController> {
                       focusNode: controller.inputFocusNode,
                       // 点击外部区域,关闭软键盘
                       // onTapUpOutside: (event) {
-                      //   controller.inputFocusNode.unfocus();
+                      //   controller.clearInputFocus();
                       // },
                       // 输入框控制器
                       controller: controller.editingController,

+ 45 - 0
lib/utils/event_bus.dart

@@ -0,0 +1,45 @@
+/// 事件回调
+typedef EventCallback = void Function(dynamic arg);
+
+/// 事件总线
+class EventBus {
+  EventBus._internal();
+
+  static final EventBus _singleton = EventBus._internal();
+
+  factory EventBus() => _singleton;
+
+  // 保存事件订阅者的订阅关系,key:事件名(id),value: 对应事件的订阅者队列
+  final _registry = <Object, List<EventCallback>?>{};
+
+  /// 添加订阅者
+  void register(eventName, EventCallback f) {
+    _registry[eventName] ??= <EventCallback>[];
+    _registry[eventName]!.add(f);
+  }
+
+  /// 移除订阅者
+  void unRegister(eventName, [EventCallback? callback]) {
+    var list = _registry[eventName];
+    if (eventName == null || list == null) return;
+    if (callback == null) {
+      _registry[eventName] = null;
+    } else {
+      list.remove(callback);
+    }
+  }
+
+  /// 发送事件
+  void post(eventName, [arg]) {
+    var list = _registry[eventName];
+    if (list == null) return;
+    int len = list.length - 1;
+    // 反向遍历,防止订阅者在回调中移除自身带来的下标错位
+    for (var i = len; i > -1; --i) {
+      list[i](arg);
+    }
+  }
+}
+
+/// 暴露单例
+var eventBus = EventBus();

+ 27 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/InputMethodUtil.kt

@@ -6,12 +6,14 @@ import android.content.Context.CLIPBOARD_SERVICE
 import android.content.Intent
 import android.inputmethodservice.InputMethodService
 import android.os.Build
+import android.os.IBinder
 import android.provider.Settings
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
 import android.view.inputmethod.InputMethodManager
 import android.widget.EditText
 
+
 /**
  * 输入法工具类
  */
@@ -115,6 +117,23 @@ class InputMethodUtil private constructor() {
         }
 
         /**
+         * 隐藏键盘
+         */
+        fun hideKeyboard(inputMethodService: InputMethodService) {
+            val windowToken = getInputMethodWindowToken(inputMethodService)
+            if (windowToken == null) {
+                return
+            }
+
+            val context = inputMethodService.applicationContext
+            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+            imm.hideSoftInputFromWindow(windowToken, 0)
+
+            // 结束当前输入会话
+            inputMethodService.onFinishInput()
+        }
+
+        /**
          * 保持输入法显示
          */
         fun keepKeyboardShow(inputMethodService: InputMethodService) {
@@ -130,5 +149,13 @@ class InputMethodUtil private constructor() {
                 }
             }
         }
+
+        /**
+         * 获取InputMethodService的WindowToken
+         */
+        private fun getInputMethodWindowToken(inputMethodService: InputMethodService): IBinder? {
+            val dialog = inputMethodService.window
+            return dialog.window?.decorView?.windowToken
+        }
     }
 }