I want to hide (resignFirstResponder) the virtual keyboard of UITextView when 'Done' presses. Theres no 'Did End on Exit' in UITextView. In UITextField i connect the 'Did End on Exit' with an IBAction and call resignFirstResponder method. How can i do this with UITextView?
The correct way to handle this is to add a done button in an inputAccessoryView to the UITextView. The inputAccessoryView is the bar that sometimes appears above the keyboard.
In order to implement the inputAccessoryView simply add this method (or a variation thereof) and call it in viewDidLoad.
- (void)addInputAccessoryViewForTextView:(UITextView *)textView{
//Create the toolbar for the inputAccessoryView
UIToolbar* toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
[toolbar sizeToFit];
toolbar.barStyle = UIBarStyleBlackTranslucent;
//Add the done button and set its target:action: to call the method returnTextView:
toolbar.items = [NSArray arrayWithObjects:[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(returnTextView:)],
nil];
//Set the inputAccessoryView
[textView setInputAccessoryView:toolbar];
}
Then handel the button being pressed by implementing the action method you called with resignFirstResponder.
- (void) returnBreakdown:(UIButton *)sender{
[self.textView resignFirstResponder];
}
This should result in a working "Done" button appearing in a standard toolbar above the keyboard.
I'm assuming by the "Done" button you mean the return key. It's not as intuitive as you might think. This question covers it pretty well.
you could add this to an action if you want to be able to use your return key
[[self view] endEditing: YES];
Make sure you declare support for the UITextViewDelegate protocol.
#interface ...ViewController : UIViewController` in .h file. In .m file, implement below method
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES; }
Here is the Swift version of the accessory "Done" button:
#IBOutlet weak var textView: UITextView!
// In viewDidLoad()
let toolbar = UIToolbar()
toolbar.bounds = CGRectMake(0, 0, 320, 50)
toolbar.sizeToFit()
toolbar.barStyle = UIBarStyle.Default
toolbar.items = [
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: nil, action: "handleDone:")
]
self.textView.inputAccessoryView = toolbar
// -----------------
func handleDone(sender:UIButton) {
self.textView.resignFirstResponder()
}
Related
I got error when passing arguments in #selector method.
This is my code:
-(void) accessoryView : (UITextField*) textField
{
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.barStyle = UIBarStyleBlackTranslucent;
numberToolbar.items = #[[[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancelNumberPad )],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Apply" style:UIBarButtonItemStyleDone target:self action:#selector(doneWithNumberPad:textField:)]];
[numberToolbar sizeToFit];
textField.inputAccessoryView = numberToolbar;
}
-(void)doneWithNumberPad : (UITextField*) txt : (id) sender {
}
You can take help of reference variable for your textfield. Declare a global property as textfield. Keep a refernce of currently active textfield and access it in every method as per your requirement.
UITextField *activeTextField;
// UITextField Delegates
-(void)textFieldDidBeginEditing:(UITextField *)textField {
activeTextField = textField;
}
You can use this activeTextField property in your class anywhere.
You need to define your class as delegate of UITextField.
self.yourTextField.delegate = self
First: Your selector is wrong. I should be action:#selector(doneWithNumberPad::) or renaming your second method to -(void)doneWithNumberPad : (UITextField*) txt textField: (id) sender.
BUT Second: You can't send custom, additional parameters with an action method. You should access the text field over a property. In your case you can store the current text field in a property, when the editing in the text fields begin. Your view controller should implement UITextFieldDelegate to receive this event.
I have a button:
#property (weak, nonatomic) IBOutlet UIBarButtonItem *addTaskBtn;
...
// Add new task button action.
- (IBAction)addTaskBtnAction:(id)sender {
}
I want a keyboard with a textfield accessory toolbar to pop up when I press my button. That textfield should also become the firstresponder which causes kind of a paradox...
I find it impossible to show a keyboard without making it a first responder of an existing textfiled, but I am trying to create a textfield as a toolbar of a keyboard.
The best example for this is in this app: https://todoist.com/ - they managed to do exactly what I am trying to achieve.
Any ideas?
Try this code for the hidden textfield:
make txtHidden as hidden and make it first responder on button click
- (IBAction)btnOpenTextfield:(id)sender {
[self.txtHidden becomeFirstResponder];
}
- (void) setupToolbar {
UIToolbar *keyboardToolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 42)];
self.txtToolbar = [[UITextField alloc] initWithFrame:CGRectMake(8, 6, 250, 30)];
UIBarButtonItem *textBtn = [[UIBarButtonItem alloc] initWithCustomView:self.txtToolbar ];
UIBarButtonItem *postBtn = [[UIBarButtonItem alloc]initWithTitle:#"Post" style:UIBarButtonItemStyleBordered target:self action:#selector(postComment)];
[keyboardToolBar setItems: [NSArray arrayWithObjects:textBtn,postBtn,nil]];
self.txtHidden.inputAccessoryView = keyboardToolBar;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == self.txtHidden) {
[self setupToolbar];
}
return true;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self performSelector:#selector(changeResponder) withObject:nil afterDelay:0.1];
[self changeResponder];
}
- (void) changeResponder {
[self.txtToolbar becomeFirstResponder];
}
This is not the best way but you can try this till you get any other better solution
I have a scene in which I want to use picker views to get the input for multiple text boxes. I want each picker view to have a toolbar with a "Done" button that dismisses the picker view. So far I have:
//toolbar with "Done" button for picker views
UIToolbar *pickerToolBar= [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,320,44)];
[pickerToolBar setBarStyle:UIBarStyleBlackOpaque];
UIBarButtonItem *barButtonDone = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(doneWithPicker:)];
pickerToolBar.items = [[NSArray alloc] initWithObjects:barButtonDone,nil];
barButtonDone.tintColor=[UIColor blackColor];
//set up picker views
_pickerOne = [[UIPickerView alloc] init];
_pickerOne.dataSource = self;
_pickerOne.delegate = self;
self.textFieldOne.inputView = self.pickerOne;
self.textFieldOne.inputAccessoryView = pickerToolBar;
What I need is some way for the doneWithPicker method to figure out which text field is currently being edited and call resignFirstResponder.
Use the text field delegate to identify which field is active. (Make sure to set yourself up as the delegate)
#implementation WhateverViewController
{
UITextField *activeTextField;
}
...
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeTextField = textField;
}
Then, in the method that is called when your done button is tapped:
[activeTextField resignFirstResponder];
I have to dismiss the UIKeyboard while entering the "done" button when I am in UITextView.
Note: I tried it with UITextView. It works fine and I want to implement the same concept in UITextview. I have tried the
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
methods, but that has issues.
Is this possible?
Swift:
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
theTextView.resignFirstResponder()
return false
}
return true
}
UITextView does not have option to have done button, because it need to have return button. You can catch press on return button but its not really recommended. Recommended way to dismiss keyboard while editing UITextView is tap gesture recognizer on main view or other elements.
Use following code, might be useful for you :)
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
return NO;
}
return YES;
}
Ivan Alek is right , UITextView needs the return button in order to move the cursor on the next line. You can add a view over the keyboard and dismiss the keyboard from a button. Like this:
UIToolbar *toolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 30)] autorelease];
UIBarButtonItem *item2 = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(closeKeyboard)] autorelease];
UIBarButtonItem *item1 = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease];
[toolbar setItems:[NSArray arrayWithObjects:item1 , item2, nil]];
[textView setInputAccessoryView:toolbar];
And then in the closeKeyboard method you can resign the first responder.
Hope this helps.
Cheers!
add Done button on accessorary view of keyboard and implement done method with
[textView resignFirstResponder];
and don't forget to set delegate for textView.
Here is a screenshot of what I did till now:
So what I am trying to do is when you select "pick a name" Textfield I need a Picker to show up, with the input #"Jack".
Since iOS 3.2, UITextField supports the inputView property to assign a custom view to be used as a keyboard, which provides a way to display a UIPickerView:
You could use the inputView property of the UITextField, probably combined with the inputAccessoryView property. You assign your pickerView to the inputView property, and, to dismiss the picker, a done button to the inputAccessoryView property.
UIPickerView *myPickerView = [[UIPickerView alloc] init];
//myPickerView configuration here...
myTextField.inputView = myPickerView;
Like that. This will not give you a direct way to dismiss the view since your UIPickerView has no return button, which is why I recommend to use the inputAccessoryView property to display a toolbar with a done button (the bar is just for aesthetics, you might as well just use a UIButton object):
UIToolbar *myToolbar = [[UIToolbar alloc] initWithFrame:
CGRectMake(0,0, 320, 44)]; //should code with variables to support view resizing
UIBarButtonItem *doneButton =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(inputAccessoryViewDidFinish)];
//using default text field delegate method here, here you could call
//myTextField.resignFirstResponder to dismiss the views
[myToolbar setItems:[NSArray arrayWithObject: doneButton] animated:NO];
myTextField.inputAccessoryView = myToolbar;
I use this and find this a lot cleaner than adding a subview and animating the UIPicker
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
responder = textField;
if ([textField isEqual:self.txtBirthday]) {
UIDatePicker *datepicker = [[UIDatePicker alloc] initWithFrame:CGRectZero];
[datepicker setDatePickerMode:UIDatePickerModeDate];
textField.inputView = datepicker;
}
return YES;
}
it will work for you .. i have edited it .and for that you have to set delegate for textfield. and create a UIPIckrView in NIb file.
- (BOOL) textFieldShouldBeginEditing:(UITextView *)textView
{
pickrView.frame = CGRectMake(0, 500, pickrView.frame.size.width, pickrView.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.50];
[UIView setAnimationDelegate:self];
pickrView.frame = CGRectMake(0, 200, pickrView.frame.size.width, pickrView.frame.size.height);
[self.view addSubview:pickrView];
[UIView commitAnimations];
return NO;
}
Well, you could rely on the UITextFieldDelegate to handle this kind of functionality.
Inside the
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
is where you would set the text of your current UITextField as well as initializing and showing the UIPickerView.
Important notice:
You might also want to conform to the UIPickerViewDelegate.
HTH
Swift:
internal var textFieldHandlerToolBar: UIToolbar = {
let tb = UIToolbar.init(frame: CGRect.init(origin: .zero, size: CGSize.init(width: UIScreen.main.bounds.width, height: 44.0)))
let doneBarButton = UIBarButtonItem.init(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(actionDonePickerSelection))
tb.setItems([doneBarButton], animated: false)
return tb
}()
internal var pickerView: UIPickerView = {
let pv = UIPickerView.init()
return pv
}()
#objc internal func actionDonePickerSelection() {
textField.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
self.pickerView.delegate = self
self.pickerView.datasource = self
}
Use it like this:
textField.inputAccessoryView = self.textFieldHandlerToolBar
textField.inputView = self.pickerView
What you can do is, create a UIButton with custom type on UITextField. Both having equal sizes. On the touch of button you can show UIPickerView.
http://tmblr.co/ZjkSZteCOUBS
I have the code and everything laid out in my blog to do this exactly. But below, I have the basic concept laid out.
Basically the solution involves an opensource project called ActionSheetPicker on github, and implementing the function textFieldShouldBeginEditing on the UITextFieldDelegate. You can dismiss the keyboard there and provide a UIPickerView instead. The basic code is listed here:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// We are now showing the UIPickerViewer instead
// Close the keypad if it is showing
[self.superview endEditing:YES];
// Function to show the picker view
[self showPickerViewer :array :pickerTitle];
// Return no so that no cursor is shown in the text box
return NO;
}
ViewController.h
#interface ChangeCurrencyVC : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
NSArray *availableCurreniesArray;
}
#property (weak, nonatomic) IBOutlet UITextField *chooseCurrencyTxtFldRef;
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
availableCurreniesArray = #[#"Indian Rupee", #"US Dollar", #"European Union Euro", #"Canadian Dollar", #"Australian Dollar", #"Singapore Dollar", #"British Pound", #"Japanese Yen"];
// Do any additional setup after loading the view.
[self pickerview:self];
}
#pragma mark - picker view Custom Method
-(void)pickerview:(id)sender{
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
// set change the inputView (default is keyboard) to UIPickerView
self.chooseCurrencyTxtFldRef.inputView = pickerView;
// add a toolbar with Cancel & Done button
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneTouched:)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelTouched:)];
// the middle button is to make the Done button align to right
[toolBar setItems:[NSArray arrayWithObjects:cancelButton, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], doneButton, nil]];
self.chooseCurrencyTxtFldRef.inputAccessoryView = toolBar;
}
#pragma mark - doneTouched
- (void)cancelTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.chooseCurrencyTxtFldRef resignFirstResponder];
}
#pragma mark - doneTouched
- (void)doneTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.chooseCurrencyTxtFldRef resignFirstResponder];
// perform some action
}
#pragma mark - The Picker Challenge
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [availableCurreniesArray count];
}
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component{
return availableCurreniesArray[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.chooseCurrencyTxtFldRef.text = availableCurreniesArray[row];
}