How to hide inputAccessoryView without dismissing keyboard
Asked Answered
N

10

13

I am using a toolbar in the inputAccessoryView property of a textView. When the keyboard shows, it displays the toolbar as expected. When the device is rotated I want to remove the toolbar. I tried:

 myTextView.inputAccessoryView.hidden = !layoutIsPortrait;

This does hide the toolbar, but leaves the outline of the taller keyboard behind. The keyboard is apparently still sized to fit the toolbar. It looks bad and interferes with touch events of underlying responders.

 myTextView.inputAccessoryView = nil;

Works only if I resignFirstResponder, then becomeFirstResponder again. This is not acceptable. I lose the cursor placement and content of the textView, keyboard flashes out and back.

[myTextView.inputAccessoryView removefromSuperview];

Does nothing at all. I saved a reference to the toolbar in a iVar and addressed that instead,

[myIvarReference removeFromSuperview];

That works, but again the taller outline of the keyboard is faintly visible. This time it does not interfere with touches of other views. So now this is a working solution but visually unacceptable. What else can I try to show and hide the inputAccessoryView at will?

Screenshot- the faint line above the keyboard is remnant of the removed toolbar

Rotated keyboard with toolbar removed

Nicko answered 24/9, 2012 at 20:45 Comment(4)
Would you mind posting a screen shot of what you mean by "the outline of the taller keyboard"? I feel like the solutions that you have mentioned should work (one of them at least), but I'm not sure what is esthetically acceptable to you...Sewing
I added a close up of the screenshotNicko
I can't test it right now but does myTextView.inputAccessoryView.frame = CGRectZero do what you're looking for?Sewing
I can't try it at the moment either. I expect that would be same result as removeFromSuperView. My guess is that it is the view that encompasses the keyboard and the toolbar together that needs resized. I don't know how I would cause that to happen without getting into some private api territory.Nicko
N
2

Never found a way to alter the frame of the keyboard. Ultimately decided to forego the inputAccessoryView, add my toolbar directly to the view as a subview and animate it myself along with the keyboard directly. This keeps the two independent and so, no more line.

Nicko answered 5/10, 2012 at 10:37 Comment(0)
C
32
myTextView.inputAccessoryView = nil;
[myTextView reloadInputViews];

This removes the toolbar from the view and reloads the view. This way you don't need to call resignFirstResponder and becomeFirstResponder. Additionally, this will still keep your cursor placement and content.

Courteous answered 30/3, 2013 at 1:18 Comment(2)
Thanks. I was looking for this. This one should be the accepted answer. 1 up!Forras
Thanks. I used relaodInputViews to make changes in the toolbar become visible without going through the resign/become FirstResponderYield
M
6

None of the answers above were working for me and reloadInputViews was causing weird issues. Eventually I got it to show and hide and have touches passthrough by doing:

Hide it:

[textview.inputAccessoryView setHidden:YES];
[textview.inputAccessoryView setUserInteractionEnabled:NO];

Show it:

[textview.inputAccessoryView setHidden:NO];
[textview.inputAccessoryView setUserInteractionEnabled:YES];
Madrid answered 29/5, 2014 at 23:39 Comment(1)
It is the best answer it doesn't cause input view to reload and doesn't slow down input typingDiaphony
R
5

For me Eric's solution never actually reset the frame or the touch areas. Presumably it's a bug with how Apple handles things. However, I found a workaround that solved the problem for me. When I set a new inputAccessoryView without a frame, reloadInputViews worked fine:

myTextView.inputAccessoryView = [[UIView alloc] initWithFrame: CGRectZero];
[myTextView reloadInputViews];
Restrictive answered 3/6, 2013 at 21:17 Comment(0)
N
2

Never found a way to alter the frame of the keyboard. Ultimately decided to forego the inputAccessoryView, add my toolbar directly to the view as a subview and animate it myself along with the keyboard directly. This keeps the two independent and so, no more line.

Nicko answered 5/10, 2012 at 10:37 Comment(0)
H
2

Xamarin code is

Control.InputAccessoryView = new UIView(CGRect.Empty);
Control.ReloadInputViews();
Hardwick answered 16/1, 2015 at 15:50 Comment(3)
Generally speaking, an answer should consist of more than just a code snippet, like some explanation of why it works.Fey
it was just jungziege's answer re-written for xamarin..................................Hardwick
Then attribute your answer as such, something like "Converting Jungziege's answer to C# and Xamarin yields..." Particularly in the case where your answer builds on somebody else answer it's useful and polite to reference the original answer as well.Fey
C
1

Oddly enough, none of these approaches worked in my case.

I have a searchcontroller which pops up a standard Apple iOS keyboard if a particular search scope is selected, and a custom keyboard view with a collection view as the input field in cases of other scopes being selected. In both cases, an undesired accessory view was drawn on the screen when the input view was displayed.

So,

self.mySearch.searchbar.inputAccessoryView = nil // did not work

[self.mySearch.searhbar.inputAccessoryView setHidden:YES] // did not work

self.mySearch.inputAccessoryView = nil  // did not work

self.mySearch.searchbar.inputAccessoryView.frame = CGRectZero //did not work

[self.mySearch reloadInputViews]

and various combinations thereof etc, etc.

What did work was to delete to individual accessory items from the accessory view:

 // insert after assignments of mySearch delegates
UITextInputAssistantItem *junk = [self.mySearch inputAssistantItem];
junk.leadingBarButtonGroups = @[];
junk.trailingBarButtonGroups = @[];
Capetian answered 5/4, 2017 at 17:30 Comment(1)
does not work as expected causes input refresh and slow downs text entryDiaphony
P
1
mTextView.inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
[mTextView reloadInputViews];

works for me, setting inputAccessoryView to nil will not work, I just don't know why.

Purifoy answered 29/12, 2017 at 14:29 Comment(1)
It worked. I was trying to add Two toolbars. Fist I was adding default and second I was trying to add when a text has been selected. When I use relaodInputViews it worked.Emera
W
0

Based on Eric Appel's answer:

myTextView.inputAccessoryView = nil;
[myTextView reloadInputViews];
hideInputAccessoryView = YES;

Further modify:

- (BOOL)canBecomeFirstResponder
{
    BOOL showInputAccessoryView = YES;

    if (hideInputAccessoryView)
        showInputAccessoryView = NO;

    return showInputAccessoryView;
}

This should hide InputAccessoryView even when the keyboard is resigned.

Waldenses answered 27/5, 2016 at 5:24 Comment(0)
E
0

Xcode 11.6 and iOS 13.6

I was trying to add two toolbars when the keyboard appears.

First, I added on viewDidLoad

self.textView.inputAccessoryView = self.addDefaultToolbar()

When the keyboard appeared, then I selected a text in UItextView and trying to add the second toolbar option

Here's code which is NOT showing a Toolbar on a selection of text.

func textViewDidChangeSelection(_ textView: UITextView) {
    if let selectedRange = textView.selectedTextRange{
        let selectedText = textView.text(in: selectedRange)
        if selectedText != nil && selectedText!.count > 0{
            print("selectedText - \(selectedText!)")
            
            if self.defaultToolBar != nil{
                self.defaultToolBar?.removeFromSuperview()
                self.defaultToolBar = nil
            }
            
            self.textView.inputAccessoryView = self.addSelectionToolbar()
        }
        else{
            print("not selectedText - \(selectedText!)")
            
            if self.selectionToolBar != nil{
                self.selectionToolBar?.removeFromSuperview()
                self.selectionToolBar = nil
            }
            
            
            self.textView.inputAccessoryView = self.addDefaultToolbar()
            
        }
    }
}

After adding a self.textView.reloadInputViews(), I was able to see change second toolbar and vice versa.

Working code.

func textViewDidChangeSelection(_ textView: UITextView) {
    if let selectedRange = textView.selectedTextRange{
        let selectedText = textView.text(in: selectedRange)
        if selectedText != nil && selectedText!.count > 0{
            print("selectedText - \(selectedText!)")
            
            if self.defaultToolBar != nil{
                self.defaultToolBar?.removeFromSuperview()
                self.defaultToolBar = nil
            }
            
            self.textView.inputAccessoryView = self.addSelectionToolbar()
            self.textView.reloadInputViews()
        }
        else{
            print("not selectedText - \(selectedText!)")
            
            if self.selectionToolBar != nil{
                self.selectionToolBar?.removeFromSuperview()
                self.selectionToolBar = nil
            }
            
            
            self.textView.inputAccessoryView = self.addDefaultToolbar()
            self.textView.reloadInputViews()
            
        }
    }
}
Emera answered 31/8, 2020 at 4:27 Comment(0)
O
0

Swift 5

I use this:

view.autocorrectionType = .no
Oneida answered 10/11, 2020 at 7:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.