InputAccessoryView docked at bottom

后端 未结 5 1542
挽巷
挽巷 2020-12-04 08:13

I\'m trying to achieve similar positioning behavior as the bottom text input bar in Apple\'s Messages app.

I have tried many approaches, searched high and low and th

相关标签:
5条回答
  • 2020-12-04 08:38

    There's an excellent, easy-to-implement, open-source solution to this from the good folks at Slack: SlackTextViewController.

    Here's how to implement a view with a docked toolbar in four steps:

    1. Install the pod into your project. (http://cocoapods.org/?q=SlackTextViewController)
    2. If you're writing an app in Swift, create a header to bridge between your Swift code and their Obj-C classes. Here's a nice quick walkthrough on that. (The bridging header won't be necessary once the classes are translated into Swift, anyone want to collaborate on that?)
    3. Create a MessageViewController that inherits from SLKTextViewController, no need to write any more code than this:

      import Foundation
      import UIKit
      
      class MessageViewController: SLKTextViewController {
      
          required init(coder aDecoder: NSCoder!) {
              super.init(coder: aDecoder)
          }
      }
      
    4. In Storyboard, create a View Controller that inherits from MessageViewController.
    5. Test the app on a device or emulator, you'll see a beautiful docked textbar that also (as a bonus) expands as the user writes additional lines of text.

    Props to the team at Slack for extracting such a useful pod.

    0 讨论(0)
  • 2020-12-04 08:49

    I was just shown "the" solution by Jason Foreman (@threeve). On your view controller (yes, view controller) add inputAccessoryView: and return the view you want to dock at the bottom and move with the keyboard. It just works. The view doesn't actually need to be in your view hierarchy it will be inserted by the view controller automatically.

    edit: also implement canBecomeFirstResponder and return YES (as noted by Max Seelemann). reloadInputViews can be handy too.

    0 讨论(0)
  • 2020-12-04 08:50

    Jonathan Badeen's aforementioned solution worked for me. Here's code from Arik showing how to implement it (this should go in your appropriate view controller):

        - (BOOL)canBecomeFirstResponder{
    
            return YES;
    
        }
    
        - (UIView *)inputAccessoryView{
    
            return self.inputAccessoryToolbar;  
         // where inputAccessoryToolbar is your keyboard accessory view
    
        }
    
    0 讨论(0)
  • 2020-12-04 08:51

    For those looking for Swift version:

    Connect your toolbar (in my case 'myToolBar') on to your view controller. Then override canBecomeFirstResponder method and override the getter inputAccessoryView variable. Also don't forget to add the self.myToolBar.removeFromSuperview() or else xcode will complain.

    class ViewController: UIViewController {
    
        @IBOutlet var myToolBar: UIToolbar!
    
        override func canBecomeFirstResponder() -> Bool {
            return true
        }
    
    
        override var inputAccessoryView:UIView{
            get{
                return self.myToolBar
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.myToolBar.removeFromSuperview()
        }
    }
    
    0 讨论(0)
  • 2020-12-04 08:53

    So I know this is an old post and I am not sure if you resolved this or not, but I found a way to get this working. I believe there is a bug in the inputAccessoryView, but I created a hacky solution to behave the way the messages app does. I think I provided all the necessary code to implement the work around. I am going to try and get a more appropriate blog post created sometime in the near future, with a more in depth description with my findings. Any questions, let me know.

    @property(nonatomic,assign)BOOL isFirstKeyboard; //workaround for keyboard bug
    
    @property(nonatomic,assign)BOOL isViewAppear;
    
    @property(nonatomic,strong)ChatBarView *chatView; //custom chat bar view
    
    @property(nonatomic,strong)UIView *footerPadView; //just to add some nice padding
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //in the view did load
    - (void)viewDidLoad
    {
        //more app specific code...
        self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
        self.chatView.textView.inputAccessoryView = self.chatView;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    -(void)done
    {
        self.isFirstKeyboard = YES;
        [self.chatView.textView becomeFirstResponder];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up
    {
        if(!self.isViewAppear)
            return;
        //NSLog(@"keyboard is: %@", up ? @"UP" : @"Down");
        if(!up && !self.isFirstKeyboard)
            [self performSelector:@selector(done) withObject:nil afterDelay:0.01];
        else if(!up & self.isFirstKeyboard)
        {
            self.isFirstKeyboard = NO;
            [self.view addSubview:self.chatView];
            CGRect frame = self.chatView.frame;
            frame.origin.y = self.view.frame.size.height - self.chatView.frame.size.height;
            self.chatView.frame = frame;
        }
        else
        {
            NSDictionary* userInfo = [aNotification userInfo];
            NSTimeInterval animationDuration;
            UIViewAnimationCurve animationCurve;
            CGRect keyboardEndFrame;
    
            [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
            [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
            [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    
            // Animate up or down
            [UIView beginAnimations:nil context:nil];
            if(up)
                [UIView setAnimationDuration:0.2];
            else
                [UIView setAnimationDuration:0.3];
            [UIView setAnimationCurve:animationCurve];
    
            CGRect frame = self.footerPadView.frame;
            CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
            if (up)
                frame.size.height = keyboardFrame.size.height - self.chatView.frame.size.height;
            else
                frame.size.height = 0;
            self.footerPadView.frame = frame;
            self.tableView.tableFooterView = self.footerPadView;
            [UIView commitAnimations];
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void)keyboardWillShow:(NSNotification *)aNotification {
        [self moveTextViewForKeyboard:aNotification up:YES];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void)keyboardWillHide:(NSNotification *)aNotification
    {
        [self moveTextViewForKeyboard:aNotification up:NO];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    
    0 讨论(0)
提交回复
热议问题