【问题标题】:Replace inputAccessoryView of keyboard in UIWebView in Swift在 Swift 中替换 UIWebView 中键盘的 inputAccessoryView
【发布时间】:2015-07-30 12:11:25
【问题描述】:

我一直在寻找一个简单的答案,但似乎找不到。

如果键盘上存在附件视图,我想查找并替换附加到我的 UIWebView 的键盘的 inputAccessoryView。我想更换它,这样我就可以拥有自己的 Prev 和 Next 按钮。快速完成是一个加分项。

听起来很简单,但并不明显。

【问题讨论】:

  • 我不相信这很容易实现。以下有一些讨论和代码链接可能对您有所帮助:stackoverflow.com/questions/19961369/…
  • 我想通了。我将在这里发布代码,但我所做的是向 UIViewController 添加了一些扩展(尽管我可能已经将它们添加到 UIWebView),遍历 UIView 和任何子视图,直到找到描述为“

标签: ios swift uiwebview keyboard inputaccessoryview


【解决方案1】:
import UIKit

extension UIViewController {

    func addNewAccessoryView(oldAccessoryView:UIView)
    {
        var frame = oldAccessoryView.frame;
        var newAccessoryView = UIView(frame:frame)
        newAccessoryView.backgroundColor = UIColor.lightGrayColor()

        let fn = ".HelveticaNeueInterface-Bold"
        var doneButton = UIButton(frame:CGRectMake(frame.size.width-80,6,100,30))
        doneButton.setTitle("Done", forState: UIControlState.Normal)
        doneButton.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        doneButton.titleLabel!.font = UIFont(name: fn, size: 15)
        doneButton.addTarget(self, action: "buttonAccessoryDoneAction:", forControlEvents: UIControlEvents.TouchUpInside)

        var prevButton = UIButton(frame:CGRectMake(2,6,50,30))
        prevButton.setTitle("<", forState: UIControlState.Normal)
        prevButton.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        prevButton.titleLabel!.font = UIFont(name: fn, size: 15)
        prevButton.addTarget(self, action: "buttonAccessoryPrevAction:", forControlEvents: UIControlEvents.TouchUpInside)

        var nextButton = UIButton(frame:CGRectMake(35,6,50,30))
        nextButton.setTitle(">", forState: UIControlState.Normal)
        nextButton.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        nextButton.titleLabel!.font = UIFont(name: fn, size: 15)
        nextButton.addTarget(self, action: "buttonAccessoryNextAction:", forControlEvents: UIControlEvents.TouchUpInside)

        newAccessoryView.addSubview(prevButton);
        newAccessoryView.addSubview(nextButton);
        newAccessoryView.addSubview(doneButton);

        oldAccessoryView.addSubview(newAccessoryView)

    }

    func traverseSubViews(vw:UIView) -> UIView
    {
        if (vw.description.hasPrefix("<UIWebFormAccessory")) {
            return vw
        }

        for(var i = 0 ; i < vw.subviews.count; i++) {
            var subview = vw.subviews[i] as UIView;
            if (subview.subviews.count > 0) {
                var subvw = self.traverseSubViews(subview)
                if (subvw.description.hasPrefix("<UIWebFormAccessory")) {
                    return subvw
                }
            }
        }
        return UIView()
    }

    func replaceKeyboardInputAccessoryView()
    {
        // locate accessory view
        let windowCount = UIApplication.sharedApplication().windows.count
        if (windowCount < 2) {
            return;
        }

        let tempWindow:UIWindow = UIApplication.sharedApplication().windows[1] as UIWindow
        var accessoryView:UIView = traverseSubViews(tempWindow)
        if (accessoryView.description.hasPrefix("<UIWebFormAccessory")) {
            // Found the inputAccessoryView UIView
            if (accessoryView.subviews.count > 0) {
                self.addNewAccessoryView(accessoryView)
            }
        }
    }

    // Override these in your UIViewController
    func buttonAccessoryNextAction(sender:UIButton!)
    {
        println("Next Clicked")
    }

    func buttonAccessoryPrevAction(sender:UIButton!)
    {
        println("Prev Clicked")
    }

    func buttonAccessoryDoneAction(sender:UIButton!)
    {
        println("Done Clicked")
    }        
}

然后当键盘出现时,从您的UIViewController 内部设置一个Notification。您可以在 viewDidAppear() 内部执行此操作。

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardDidShow:"), name:UIKeyboardDidShowNotification, object: nil);

并从您的keyboardDidShow 处理程序中调用UIViewControllerreplaceKeyboardInputAccessoryView 方法。

func keyboardDidShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.replaceKeyboardInputAccessoryView()
    }
}

【讨论】:

  • 你能告诉我你用let tempWindow:UIWindow = UIApplication.sharedApplication().windows[1] as UIWindow访问哪个窗口
  • 这个解决方案会被苹果拒绝吗?
【解决方案2】:

user3670534 解决方案可以正常工作,但如果窗口顺序发生更改,您可以使用以下方法获取正确的窗口:

var tempWindow: UIWindow!;
for window in UIApplication.sharedApplication().windows {
    if (window.description.hasPrefix("<UITextEffectsWindow")) {
        tempWindow = window
    }
}

【讨论】:

    【解决方案3】:

    我发布了一个要点来实现这一点: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66

    这是一个UIWebView 类别,您只需更改customInputAccessoryView 属性:

    @interface UIWebView (CustomInputAccessoryView)
    
    @property (strong, nonatomic) UIView *customInputAccessoryView;
    
    @end
    

    请记住,这使用私有 API,因此使用风险自负,但似乎很多应用都在做类似的事情。

    【讨论】:

      【解决方案4】:

      在 Swift 3 中

      我删除了内置的附件视图,然后用 XIB 构建了一个自己的视图。 (感谢@Rob) 这显示了如何删除内置视图:

      WebViewExtensions.swift:

      import UIKit
      
      extension UIViewController {
          func removeInputAccessoryView() {
              // locate accessory view
              let windowCount = UIApplication.shared.windows.count
              if (windowCount < 2) {
                  return;
              }
      
              let tempWindow:UIWindow = UIApplication.shared.windows[1] as UIWindow
              let accessoryView:UIView = traverseSubViews(vw: tempWindow)
              if (accessoryView.description.hasPrefix("<UIWebFormAccessory")) {
                  // Found the inputAccessoryView UIView
                  accessoryView.removeFromSuperview()
              }
          }
      
          func traverseSubViews(vw:UIView) -> UIView
          {
              if (vw.description.hasPrefix("<UIWebFormAccessory")) {
                  return vw
              }
      
              for i in (0  ..< vw.subviews.count) {
                  let subview = vw.subviews[i] as UIView;
                  if (subview.subviews.count > 0) {
                      let subvw = self.traverseSubViews(vw: subview)
                      if (subvw.description.hasPrefix("<UIWebFormAccessory")) {
                          return subvw
                      }
                  }
              }
              return UIView()
          }
      }
      

      WKWebView

      override func viewDidLoad() {
              super.viewDidLoad()
      
              NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardDidShow, object: nil, queue: nil) { (notification) in                
      
                  if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {                    
                      self.removeInputAccessoryView()
                  }
              }
      
          }
      

      通过使用上面的解决方案,可以修改它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        • 2011-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-17
        • 1970-01-01
        相关资源
        最近更新 更多