Show UIView with buttons over keyboard, like in Skype,Viber messengers (Swift, iOS)
Asked Answered
F

1

7

I want to create attachments view, that places under input accessory view, over keyboard, like in Skype App or Viber:

enter image description here

I already asked such question here, but suggested solution for this question was not so elegant, because when i drag my scroll view to the top, i want to my Attachment UIView move down with keyboard (I use UIScrollViewKeyboardDismissModeInteractive).

So i create a function, that find out the view, where keyboard and my custom input accessory view are placed:

    func findKeyboardView() -> UIView? {
       var result: UIView? = nil

       let windows = UIApplication.sharedApplication().windows
       for window in windows {
           if window.description.hasPrefix("<UITextEffectsWindow") {
               for subview in window.subviews {
                   if subview.description.hasPrefix("<UIInputSetContainerView") {
                       for sv in subview.subviews {
                           if sv.description.hasPrefix("<UIInputSetHostView") {
                               result = sv as? UIView
                               break
                           }
                       }
                       break
                   }
               }
              break
           }
       }
       return result
   }

enter image description here

And after it i add a my custom UIView and create a few constraints:

    func createAttachView() {
        attach = MessageChatAttachmentsView(frame: CGRectZero)
        let newView = findKeyboardView()
        newView!.addSubview(attach!)
        newView!.addConstraint(NSLayoutConstraint(item: accessoryView, attribute: .Bottom, relatedBy: .Equal, toItem: attach!, attribute: .Top, multiplier: 1.0, constant: 0.0))
        attach!.addConstraint(NSLayoutConstraint(item: attach!, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 260))
        attach!.addConstraint(NSLayoutConstraint(item: attach!, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 320))
    }

This create custom UIView under input accessory view and above keyboard, and it moves when i scroll up. But when i want to press on button, i press a key on keyboard.

enter image description hereenter image description here

So how can i move this view to the top of view hierarchy in UIInputSetHostView?

Family answered 16/9, 2015 at 1:53 Comment(1)
I think you should be swapping in a new inputView and reloading the input views. developer.apple.com/library/ios/documentation/StringsTextFonts/…Reiners
F
4

Okey, thanks to Brian Nickel, i found maybe not the elegant, but very simple solution. So i had override inputAccessoryView to create a toolbar over keyboard. So basically, if i press on attach button on this toolbar, i want to see another inputView, not a keyboard. So in my custom input accessory view class i created just some textView, that is hidden:

class MessageChatInputAccessoryView : UIToolbar {
    var textView:UITextView!  //textView for entering text
    var sendButton: UIButton! //send message
    var attachButton: UIButton! // attach button "+"
    var attachTextView:UITextView! --> this one 

    override init(frame: CGRect) {
        super.init(frame: frame)
        .....
        ..... 
        attachTextView = UITextView(frame: CGRectZero)
        attachTextView.alpha = 0.0
        self.addSubview(attachTextView)
        ....
     }

So in my main view controller, i created function, the re-initialize inputView for this newly created attachTextView, something like this:

func attach(sender: UIButton) {
     if attachMenuIsShown {
          accessoryView.attachTextView.inputView = accessoryView.textView.inputView
          accessoryView.attachTextView.reloadInputViews()
          attachMenuIsShown = false
       } else {
           accessoryView.attachTextView.becomeFirstResponder()
           accessoryView.attachTextView.inputView = MessageChatAttachmentsView(frame: CGRectZero)
           accessoryView.attachTextView.reloadInputViews()
           attachMenuIsShown = true
    }

}

So when i press on attach button, my attachTextView becomes first responder, and than i re-initialize input view for this textView. And i got my attachments view right under input accessory view. And when i press attach button once again, i re-initialize inputView with default inputView for my main textView, which is keyboard view.

Family answered 17/9, 2015 at 2:44 Comment(2)
Hi Pavel, I tried similar code at iOS13, the accessoryView is not showing until the real input of textView becomes first responder. Therefore attachTexttView can't becomeFirstResponder, nor reloadInputViews.Occam
Thanks for the info. I did similar thing, override var inputView: UIView? and override var canBecomeFirstResponder: Bool, for attachTextView, I made a custom subclass for attachTextView. The trick is need to call view..becomeFirstResponder() when the viewController's view didload or willAppear to trigger it for the first time.Occam

© 2022 - 2024 — McMap. All rights reserved.