2016-10-03 26 views
10

我的应用程序具有类似于iOS的邮件应用程序的视图,包含停靠在屏幕底部的文本字段工具栏风格的看法:UIWebView能否处理用户交互而不成为第一响应者?

当用户点击文本字段中输入文本,键盘滑动起来,在工具栏的幻灯片吧:

我已经通过使工具栏上查看UITableViewControllerinputAccessoryView并使其主要view实现了这个第一响应者。主体文本“这是链接...”实现为UIWebView,因为它使用来自Web服务的HTML填充,并且需要支持格式和链接。

我遇到的问题是,当用户点击该UIWebView任何地方,它成为第一个响应和inputAccessoryView隐藏自身:

,我不希望发生的事情。我需要用户能够点击网页视图中的链接,以便它不会响应用户交互不是一种选择。

UIWebView是否成为第一响应者来处理水龙头?如果是这样,webview可以处理链接上的水龙头,但是将触摸事件传递给主要的view,并使第一响应者再次立即离开?任何关于如何解决这个问题的指针都会被感激地收到。

UPDATE:

这样看来,网络视图不已经成为第一个响应者来处理链接的水龙头,我可以破解我的方式解决这个问题有:

extension UIView { 

    public override func becomeFirstResponder() -> Bool { 
     // Actual view is instance of private class UIWebBrowserView, its parent parent view is UIWebView 
     if self.superview?.superview is UIWebView { 
      return false 
     } else { 
      return super.becomeFirstResponder() 
     } 
    } 

} 

谁能告诉我如何以非hacky的方式达到上述目的?

+0

我希望这种联系将是有益的http://stackoverflow.com/a/14646530/3259690 –

+0

感谢约杰什但是这并不完全符合我要找的。 – fractious

回答

1

我可以在这里提供两件事。一个快速和肮脏的解决方案(我希望)和一个建议(或者你可能称之为我感到惊讶)。

肮脏的解决方案:实施这样的事情

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { 
    self.shouldCloseKeyboard = false 
    return true 
} 

func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { 
    return self.shouldCloseKeyboard 
} 

@IBAction func inputDone(_ sender: AnyObject) { 
    if self.inputField.isFirstResponder { 
     self.shouldCloseKeyboard = true 
     self.inputField.resignFirstResponder() 
    } 
} 

inputDone:将连接到你的“邮报”按钮,显然也包含你需要发布到做其他(或者你把在textFieldShouldEndEditing如果并在关闭它之前,即完成输入)。 shouldCloseKeyboard是一个Bool变量,它初始化为false,但随后按照您在此处所看到的方式使用。显然inputField是你的文本字段(不是整个附件视图!),整个类符合UITextFieldDelegate,文本字段通过Interface Builder(或其他方式)将其实例设置为delegate

这应该像您打算的那样行事。我在一个示例项目中尝试了它,尽管我没有使用像您这样的工具栏(见下文)或将所有内容放入表格中。我只是做了一个简单的web视图,下面有一个输入和一个按钮来关闭东西。一旦文本字段是第一响应者,即键盘已经弹起,我可以在web视图中点击,跟随链接等,并且键盘不会消失。当点击按钮时,它正确关闭(然后我没有打扰什么是第一响应者)。

现在让我感到吃惊的是:起初我认为它简单地使用工具栏作为inputAccessoryView让它在键盘上移动是一个不错的窍门。然而,在进一步的思考中,我得出的结论是,我不会这样做(而是在显示键盘时手动移动视图,以及其他任何东西。您可能也必须这样做,以确保没有任何重要的是被键盘或配件视图遮挡)。原因是配件视图不应该在其他地方的视图层次结构中。事实上,当我在演示项目中迅速尝试它时(我将按钮和文本字段嵌入到UIView中,为此定义了一个插座,然后在代码中将其设置为inputAccessoryView,尝试在各个位置尝试)应用程序崩溃。这是合理的,因为textfield本身就是容器的子视图,它将成为配件,但同时也是视图控制器主视图的一个孩子......我很惊讶你设法克服这一切。

总之,这种方法看起来像一个麻烦。我理解输入附件视图的方式,它们更多的是用于附加视图,而不是用于已经在屏幕上呈现的控件(因此已经是视图层次结构的一部分)。在另一个项目中,我专门避免通过简单地伪造它来解决这个问题:我有一个单独的视图作为附件加载,看起来就像它与“关联”的控件一样。一旦显示这个虚假的视图,我将第一响应者切换到它(以及它的一个子视图,一个文本字段,所以键盘保持不变),我的用户可以编辑。一旦按下完成按钮,我将输入复制到“原始”文本字段,全部都是neato。因此,从长远来看,我会建议你(或任何人)重新考虑将现有视图作为配件搞乱,而是选择“常规”视图在需要的位置移动,并保留配件视图作为“附加帮助者”。

UPDATE:

好了,我上面描述(在“快速和肮脏的”溶液)假设你只想要一种方式编辑出,即防止任何别的成为第一响应者,并且只有在按下“完成”后才让其失去第一响应者。

关于webView它完成同样的事情。当试图只有阻止webView成为第一响应者的问题是如何识别是什么导致文本字段丢失第一响应者状态。我认为你的“hacky”方法指向了正确的方向,但是由于你不应该在扩展中重写方法(iirc),所以我建议在这种情况下继承UIWebView。然后,您也可以给它一个打开和关闭该行为的属性(即,如果文本字段成为第一响应者/开始编辑,则将其打开,一旦失去它,将其关闭)。这应该是足够的子类:

class MyWebView: UIWebView { 

    public var shouldNotBecomeFirstResponder = false; 

    override public var canBecomeFirstResponder: Bool { 
     if self.shouldNotBecomeFirstResponder { 
      return false 
     } else { 
      return super.canBecomeFirstResponder 
     } 
    } 
} 

(我保证原来的行为是模仿,如果新Bool没有设置,这将导致类行为完全像在其他情况下网页视图我没尽管在你的设置中没有测试过。) 设置shouldNotBecomeFirstResponder显然应该在所有适当的位置完成。例如,我想你可以听听键盘(dis)外观通知。

一般来说,也可能有其他方法可以做到不需要子类。也许你可以使用手势识别器除了我的第一个建议上述弄清楚shouldCloseKeyboard是否必须设置与否,但这是硬可能是更多的工作和成果进行读/维护的代码。这可能是很难搞清楚什么最先被调用时,逻辑盘算web视图是否被点击(因此shouldCloseKeyboard必须设置之前它实际上成为第一个响应者!)或别的东西(在这种情况下,它被取消设置不知何故)。

所以我#d用子类去,即使子类增加了几乎没有什么web视图。 :)

+0

感谢Gero的详细回复,我会在下周尝试您的建议。 – fractious

+0

当最初实现这个我没去来回就是否实施这一使用输入附件视图,但除了这一个问题,这是一个非常可靠的合作(互动解雇也适用请客)。根据这一(诚然非常非权威性)评论苹果使用在iOS的消息同样的技术应用http://stackoverflow.com/questions/24634795/keyboard-handling-just-like-in-messages-app-in- ios-7#comment46652102_25013674我不愿以另一种方式重新实现。 – fractious

+0

肮脏的解决方案实际上并不是我正在寻找的东西,我很害怕。如果用户需要,用户应该能够结束编辑并关闭键盘(以便他们可以在需要时更好地查看下面的内容)。我已经阅读了Apple的事件处理指南,但是我仍然不清楚UIWebView *是否有*成为处理链接水龙头的第一响应者。 – fractious

相关问题