iOS开发:如何在系统键盘上方添加视图并在Globe与Mic按钮间插入分段控件
iOS开发:如何在系统键盘上方添加视图并在Globe与Mic按钮间插入分段控件
嘿,这个需求我之前帮朋友折腾过,其实核心就是要抓住系统键盘的视图结构,再结合自定义输入视图的特性来处理,下面给你一步步拆解:
第一步:监听键盘弹出事件,找到系统键盘的容器
系统键盘弹出时,我们才能拿到它的视图实例。所以首先要注册键盘显示的通知,在控制器的viewDidLoad里加这段代码:NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)记得在控制器销毁时移除监听,避免内存泄漏:
deinit { NotificationCenter.default.removeObserver(self) }第二步:定位键盘的顶部工具栏(就是放Globe和Mic的那一行)
实现keyboardDidShow方法,遍历窗口的子视图找到键盘的容器(通常类名带UIPeripheralHostView),再从里面找到顶部的工具栏(高度比键盘主体小很多):@objc private func keyboardDidShow(_ notification: Notification) { guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return } // 找到键盘的根容器视图 let keyboardHostView = keyWindow.subviews.first(where: { String(describing: type(of: $0)).contains("UIPeripheralHostView") }) guard let keyboardHost = keyboardHostView else { return } // 定位到顶部的工具栏(Globe和Mic所在的行) let topToolbar = keyboardHost.subviews.first(where: { $0.frame.height < 50 }) guard let toolbar = topToolbar else { return } // 接下来在这里插入分段控件 }第三步:创建分段控件,插入到Globe和Mic之间
先初始化我们的分段控件,然后遍历工具栏的子视图找到Globe和Mic按钮,用AutoLayout把分段控件夹在中间:// 初始化分段控件 let segmentControl = UISegmentedControl(items: ["大写", "小写"]) segmentControl.selectedSegmentIndex = 0 segmentControl.addTarget(self, action: #selector(segmentValueChanged(_:)), for: .valueChanged) toolbar.addSubview(segmentControl) segmentControl.translatesAutoresizingMaskIntoConstraints = false // 找到Globe和Mic按钮(通过accessibilityLabel判断更稳妥) let globeButton = toolbar.subviews.first(where: { $0.accessibilityLabel == "Globe" }) let micButton = toolbar.subviews.first(where: { $0.accessibilityLabel == "Microphone" }) // 布局约束,把分段控件放在两者之间 if let globeBtn = globeButton, let micBtn = micButton { NSLayoutConstraint.activate([ segmentControl.centerYAnchor.constraint(equalTo: toolbar.centerYAnchor), segmentControl.leadingAnchor.constraint(equalTo: globeBtn.trailingAnchor, constant: 8), micBtn.leadingAnchor.constraint(equalTo: segmentControl.trailingAnchor, constant: 8) ]) }这里要注意:不同iOS版本的键盘视图结构可能有小变化,所以如果找不到这两个按钮,可以退而求其次,把分段控件放在工具栏的右侧(Mic左边固定位置),保证兼容性。
第四步:处理自定义inputView的情况
当你给UITextView设置了自定义inputView时,系统键盘不会弹出,这时候我们的分段控件要通过inputAccessoryView来显示。你可以封装一个通用的工具类,或者直接给UITextView设置:// 给自定义输入视图绑定附属视图 let customInputView = YourCustomKeyboardView() textView.inputView = customInputView // 创建包含分段控件的附属视图 let accessoryToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44)) let segmentControl = UISegmentedControl(items: ["选项1", "选项2"]) accessoryToolbar.items = [UIBarButtonItem(customView: segmentControl)] textView.inputAccessoryView = accessoryToolbar这样当自定义键盘弹出时,分段控件就会显示在它的上方,和系统键盘的效果保持一致。
额外注意事项
- 每次键盘弹出时要检查是否已经添加过分段控件,避免重复添加;
- 因为我们操作了系统私有视图(比如
UIPeripheralHostView),要多做几个iOS版本的兼容性测试,避免在新系统上失效; - 如果不需要兼容太老的系统,也可以考虑用
UIInputViewController来管理自定义输入视图,它的inputAccessoryView会自动和系统键盘联动。
内容来源于stack exchange
相关产品推荐
相关产品推荐

