首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS UIAlertView UITextField 自動上移問題:輸入法安全區域避讓導致,換系統輸入法解決

     編輯:程式設計綜合問答

UIAlertView (已棄用,iOS 8+ 用 UIAlertController) 自帶輸入框,二次彈出時輸入框異常上移。經排查是第三方輸入法 (搜狗等) 安全區域避讓邏輯與 AlertView 佈局衝突。

現象復現

  1. 首次點擊按鈕彈出 AlertView,輸入框位置正常
  2. 輸入內容、關閉
  3. 再次點擊彈出,輸入框明顯上移,甚至超出可視區域

根本原因

  • 第三方輸入法 (搜狗、訊飛等) 為避免遮擋輸入框,會監聽 UIKeyboardWillShow 通知,計算安全區域並調整視圖框架
  • UIAlertView 內部佈局較舊,對鍵盤通知響應處理不當,導致二次彈出時座標計算錯誤
  • 系統自帶輸入法無此問題,或第三方輸入法「加密輸入模式」下不觸發避讓邏輯

解決方案

方案一:遷移到 UIAlertController (推薦,根治)

let alert = UIAlertController(title: "標題", message: "消息", preferredStyle: .alert)
alert.addTextField { textField in
    textField.placeholder = "請輸入"
    textField.isSecureTextEntry = false
}
alert.addAction(UIAlertAction(title: "取消", style: .cancel))
alert.addAction(UIAlertAction(title: "確定", style: .default) { _ in
    let input = alert.textFields?.first?.text ?? ""
    print("輸入: \(input)")
})
present(alert, animated: true)
  • UIAlertController 是現代 API,正確處理鍵盤避讓、安全區域、動畫
  • 支持多輸入框、Action Sheet 模式、自定義 View

方案二:檢測輸入法類型提示用戶 (不想遷移時)


// 檢測是否第三方輸入法
func isThirdPartyKeyboard() -> Bool {
    let primaryLanguage = UITextInputMode.currentInputMode?.primaryLanguage ?? ""
    return !primaryLanguage.hasPrefix("en_") && !primaryLanguage.hasPrefix("zh-Hans") && !primaryLanguage.hasPrefix("zh-Hant")
    // 簡略判斷,實際需維護白名單
}

// 彈出前提示
if isThirdPartyKeyboard() {
    let tip = UIAlertController(title: "提示", message: "檢測到第三方輸入法可能導致界面異常,建議切換系統輸入法", preferredStyle: .alert)
    tip.addAction(UIAlertAction(title: "知道了", style: .default))
    present(tip, animated: true)
}

方案三:監聽鍵盤通知手動修正 (治標)


@objc func keyboardWillShow(_ notification: Notification) {
    guard let userInfo = notification.userInfo,
          let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
          let alertView = presentedViewController as? UIAlertView else { return }
    
    // 手動調整 AlertView frame 避開鍵盤
    var frame = alertView.frame
    frame.origin.y = min(frame.origin.y, keyboardFrame.origin.y - frame.height - 20)
    alertView.frame = frame
}

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

總結

  1. 根治:棄用 UIAlertView,全面遷移 UIAlertController
  2. 繞過:切換系統輸入法或第三方輸入法「加密模式」可避免
  3. 原因:第三方輸入法安全區域避讓邏輯與舊版 AlertView 佈局衝突

已解決:項目遷移至 UIAlertController,問題徹底消失。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved