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.
Related
I have a UITextView that is created programmatically on viewDidLoad using the method below. Keyboard is shown successfully right after [_answerTextView becomeFirstResponder] is called. And hid if the user enters return(\n) character.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[self endEditing:YES];
return NO;
}
return YES;
}
After the keyboard is hid by the code above, I'm not able to bring it back anymore by tapping the UITextView again.
I tried showing the keyboard by calling [_answerTextView becomeFirstResponder] on Tap event for the parent UIView and it worked. But that's not what I want.
UITextView is created by the method below;
-(UITextView*)createSurveyTextView{
_answerTextView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, _optionsStackView.frame.size.width, 200)];
_answerTextView.keyboardType = UIKeyboardTypeDefault;
_answerTextView.text = #"";
_answerTextView.editable = true;
_answerTextView.selectable = true;
_answerTextView.delegate = self;
[_answerTextView becomeFirstResponder];
_answerTextView.backgroundColor = [UIColor whiteColor];
_answerTextView.textColor = [UIColor blackColor];
_answerTextView.layer.cornerRadius = 5;
[_optionsStackView addSubview:_answerTextView];
_answerTextView.font = [UIFont systemFontOfSize:20];
[_answerTextView setReturnKeyType:UIReturnKeyDone];
[_optionsStackView bringSubviewToFront:_answerTextView];
[self bringSubviewToFront:_answerTextView];
[_answerTextView setUserInteractionEnabled:true];
UITapGestureRecognizer *mainViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTextViewTap:)];
UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap2:)];
[_answerTextView addGestureRecognizer:mainViewTap];
[self addGestureRecognizer:tap2];
return _answerTextView;
}
I want the UITextView to simply show the keyboard when the user taps on it self. What am I missing?
Edit: I have the same sources in another view, but everything works fine there. The only difference is, here the UITextView is created programmatically.
Edit 2: I got it worked. The _optionsStackView that the UITextView is added as a child is a UIStackView. I tried adding the _answerTextView to the parent UIView and everything works fine now. What would be the problem with the UIStackView?
Your problem very strange in your code.You can explantion why use UITapGestureRecognizer to this UITextView control.How do you think this lead to conflict?
I find your problem where in start,but I create new project to ensure.So I confirm that UITextView already has target with itself.Also you can't to add UITapGestureRecognizer.
What you're doing is almost correct, but just try changing endEditing: to [textView resignFirstResponder]:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
If that doesn't work, then it could be that one of your gestures is preventing the UITextView's own UITapGestureRecognizer from receiving the tap. Try disabling (or comment out the creation of) both of your recognizers to verify that it is the issue. If it is, then you can fix it using the UIGestureRecognizerDelegate methods.
You did not use common way to hide/close the keyboard.
Try this common way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
return [textField resignFirstResponder];
}
This is a method in the UITextFieldDelegate, use it and remove your code:
if([text isEqualToString:#"\n"]) {
[self endEditing:YES];
return NO;
}
Edit:
#siburb You are right. My bad.
UITapGestureRecognizer maybe the root cause.
Edit:
#Semih Akbas
Repalce:
[_optionsStackView addSubview:_answerTextView];
To:
[_optionsStackView addArrangedSubview:_answerTextView];
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
In my iPhone app I have a UITextView added to my main view and I would like to dismiss it when user clicks anyplace in the screen outside of the UITextView boundaries.
Is it possible? What would be the best way to implement this?
Try using this
-(void)ViewDidLoad{
....
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tap:)];
[self.view addGestureRecognizer: tapRec];
....
}
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
}
You can also use i.e optional
[textView resignFirstResponder];
In UITapGestureRecognizer
-(void)tap:(UITapGestureRecognizer *)tapRec{
[yourTextView resignFirstResponder];
}
Or if it is required on clicking next then
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
I recommend to turn your mainView into a UIControl.
-(IBAction)backgroundTap:(id)sender
{
[[self view] endEditing:YES];
}
I want to show UITableView on tapping of UITextView.
key board should not be shown.
the problem is on tapping UITextView both UITableView and keyboard are shown.
I want only table view to be shown. I want to display data got from web service in UITextView which is not editable.on pressing edit button in navigation bar that time on tapping UITextView ,UITableView should be popped up and not keyboard.
My code is below:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
-(void)textViewDidBeginEditing:(UITextView *)textView{
[self.view endEditing:YES];
tableVw=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 500)];
tableVw.dataSource=self;
tableVw.delegate=self;
[self.view addSubview:tableVw];
}
-(void)viewDidLoad{
[super viewDidLoad];
txtVwDescription=[[UITextView alloc]initWithFrame:CGRectMake(10, 270, 300,stringSize.height+10)];
txtVwDescription.backgroundColor=[UIColor clearColor];
txtVwDescription.layer.cornerRadius=5;
txtVwDescription.backgroundColor=[UIColor colorWithRed:0.662745 green:0.662745 blue:0.662745 alpha:0.3];
[txtVwDescription setFont:[UIFont systemFontOfSize:13.0]];
txtVwDescription.contentInset=UIEdgeInsetsMake(0, 0, 0, 0);
[txtVwDescription setUserInteractionEnabled:NO];
txtVwDescription.editable=NO;
txtVwDescription.delegate=self;
[self.view addSubview:txtVwDescription];
}
-(void)edit{
[txtVwDescription setUserInteractionEnabled:YES];
txtVwDescription.editable=NO;
[txtVwDescription resignFirstResponder];
}
you can use UITextViewDelegate's textViewShouldBeginEditing method returning NO, and presenting there the UITableView. In such a way the keyboard should not be presented.
Rather than having to mess with textViewDelegate methods, I find it easier to simply disable editing for the textView and add a gesture recognizer to it like this:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showTableView)];
UITextView *textView = [[UITextView alloc] initWithFrame:....];
textView.editable = NO;
[textView addGestureRecognizer:tapGestureRecognizer];
This way, no keyboard is shown and you don't have to mess around with navigation inside the delegate methods. All you need to do now is handle the tap with the method you provided the recognizer:
- (void)showTableView {
// do stuff here
}
EDIT:
You might want to also consider using a UILabel instead of a UITextView if you are not planning on making it editable at all. You can implement the same gesture recognizer code as well, just add it to the label instead of the textView.
UITextField and UITextView classes has a property named inputView for displaying custom views instead of the default keyboards. The system shows whatever UIView descendant class you set to that property when the textfield/view becomes first responder. So simply add,
UITextView *textView = [[UITextView alloc] initWithFrame:someFrame];
textView.inputView = self.myTableView; //this is your already initialised tableview
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()
}