iPhone - possible to not show keyboard but still show the cursor in a UITextField? - iphone

I have a custom keyboard I want to show when the user taps a UITextField. But at the same time I want to show the cursor in the textfield. If if return a NO for canBecomeFirstResponder, it doesn't show the default keyboard but doesn't show the cursor either.
Can someone please help me out?
Thanks.

The answer to your problem is to create a view for your custom keyboard and then edit the inputView property of your UITextField and pass it the view for your custom keyboard.
I hope that helps.

override following two methods in UITextFieldDelegate. Note that this approach is valid for both UITextField and UITextView (in which case you override corresponding methods in UITextViewDelegate)
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (!textField.inputView) {
//hides the keyboard, but still shows the cursor to allow user to view entire text, even if it exceeds the bounds of the textfield
textField.inputView = [[UIView alloc] initWithFrame:CGRectZero];
}
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
return NO;
}

Seems like what you want is a UITextField with a custom keyboard. Create the class CustomKeyboard : UIView and add buttons/layout the view. Then for your textfield just set the inputView property to an instance of the class CustomKeyboard textField.inputView = customKeyboard;. You'll need to set the inputView property to be readwrite as well #property (readwrite, retain) UIView *inputView; By setting the inputView property, the standard iPhone keyboards will not appear when the textfield becomes first responder.

Register as keyboard notification observer (e.g. in the view controller where you want to hide the keyboard):-
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(hideKeyboard:) name:UIKeyboardWillShowNotification object:nil];
Put in the hideKeyboard: function:-
-(void)hideKeyboard:(NSNotification *)notification {
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
for (UIView *keyboard in [keyboardWindow subviews]) {
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES) {
keyboard.alpha = 0;
}
}
}
}
(Thanks to luvieere in this post for showing me how to get the keyboard)

I'm not sure of the point, but why not just use a UILabel with the same contents of the text field and decorated to look like your text field with a cursor in it. Swap it out for a UITextField when you want input.

There are 2 solutions to your problem.
1) Setting the alpha of the keyboard to 0 will make the keyboard invisible... which may be all you want. The cursor will appear.
2) UITextField implements the UITextInputTraits Protocol. It will always call the keyboard when it becomes the first responder. You will need to inherit from either it or anther class to change that default behavior.
Good luck.
If you tell us what your trying to accomplish we might be about to suggest a more elegant way of accomplishing it.
Have fun.

I see two solutions - either create custom animation (and stop or start it depending on the first responder status of the text field), or play with inputView property.
Here is a solution for inputView approach:
Set inputView property of the UITextField to empty view and ask it to become first responder. This will effectively hide default inputView (i.e. keyboard), but will continue showing blinking cursor.
Add Tap gesture recognizer, and when user taps UITextField, set the inputView property to your custom keyboard, dismiss the keyboard and ask the UITextField to become first responder again.
class BlinkingTextFieldVC: UIViewController {
var blinkingTextField: UITextField!
override func onViewDidLoad() {
setupView()
}
func setupView() {
blinkingTextField = UITextField()
blinkingTextField.inputView = UIView() // empty view will be shown as input method
blinkingTextField.becomeFirstResponder()
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(blinkingTextFieldTapped(_:)))
blinkingTextField.addGestureRecognizer(tapGuesture)
}
func blinkingTextFieldTapped(_ gesture: UITapGestureRecognizer) {
if gesture.state == .ended {
view.endEditing(true)
blinkingTextField.inputView = nil // set your custom input view or nil for default keyboard
blinkingTextField.becomeFirstResponder()
}
}
}

Why do you even need the cursor ?
I think all you need to do, is when ever a user press a key on your own keyboard, you can update the text value of the input.

Related

Auto Adjust UITextView and UITextField on appearance on keyboard [duplicate]

This question already has answers here:
How can I make a UITextField move up when the keyboard is present - on starting to edit?
(98 answers)
Closed 9 years ago.
I have a project which Im working on this time and I would like to adjust the UITextView and UITextField above the keyboard when it appears, because when the keyboard appears the TextView and TextField and hidden behind it.
Here are my screen shots,
Without Keyboard:
And with the keyboard,
This is a fairly common problem, there are all sorts of solutions to it. I put one together and made it part of my EnkiUtils package which you can download from https://github.com/pcezanne/EnkiUtils
Short version: You'll want to watch for keyboard events and call the Enki keyboardWasShown method, passing it the current view (and cell if you are in a table).
Long Version: Here's the text from my blog (http://www.notthepainter.com/expose-the-uitextfield-when-keyboard-is-shown/)
Notice that it is a class method, not an instance method. I keep a class called EnkiUtilities around to hold useful things. To call it, we first set up our observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
And in the keyboardWasShown method we call our utilities method:
- (void)keyboardWasShown:(NSNotification*)aNotification
{
[EnkiUtilities keyboardWasShown:aNotification view:self scrollView:myTableView activeField:activeField activeCell:activeCell];
}
So what is activeField and activeCell? Lets look at our textViewDidBeginEditing method to see how those are set
-(void)textViewDidBeginEditing:(UITextView *)sender
{
activeField = sender;
if ([sender isEqual:descriptionTextView]) {
activeCell = descriptionCell;
if (shouldClearDescription) {
[descriptionTextView initWithLPLStyle:#""];
shouldClearDescription = false;
}
}else if ([sender isEqual:hintTextView]) {
activeCell = hintCell;
if (shouldClearHint) {
[hintTextView initWithLPLStyle:#""];
shouldClearHint = false;
}
} else {
activeCell = nil;
}
}
This method is called when a UITextField begins editing. I set the activeField to the sender and then I set the activeCell to the cell that corresponds to the field.
The only bit remaining is to restore the view when the keyboard disappears.
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
myTableView.contentInset = contentInsets;
myTableView.scrollIndicatorInsets = contentInsets;
}
When you are working without a UITableView, just put the text fields into a UIScrollView and pass that, not the UITableView, to keyboardWasShown.

Hide IOS keyboard with multiple textFields

I have 2 textFields side by side, countryCodeTextField and cellphoneTextField
On countryCodeTextField. I have an action selectCountry that happens on Edit Did Begin on the countryCodeTextField
- (IBAction)selectCountry:(id)sender {
countryCodeTextField.delegate = self;
[countryCodeTextField resignFirstResponder];
Note that self implements the <UITextFieldDelegate>.
Problem is when user click's cellphone the keyboard is displayed if he clicks on countryCodeTextField the keyboard is never dismissed.
If the person clicks the countryCode first then the keyboard never appears(which is what I want).
Why isn't the keyboard hidden when the user clicks cellphoneTextField first and then countryCodeTextField?
If you don't want the user to be able to edit a particular UITextField, set it to not be enabled.
UITextField *textField = ... // Allocated somehow
textfield.enabled = NO
Or just check the enabled checkbox in Interface Builder. Then the textfield will still be there and you'll be able to update it by configuring the text. But as sort of mentioned in comments, users expect UITextFields to be editable.
Also, why are you setting the delegate in the IBAction callback? I would think you'd be better off doing this in Interface Builder or when you create the UITextField in code.
EDIT:
Ok - so you want users to be able to select the box, but then bring up a custom subview(s) from which they select something which will fill the box.
So set the UITextField delegate when you create it (as mentioned above) and implement the following from the UITextFieldDelegate protocol:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO;
}
to return NO. Note that if you are using the same delegate for both of your UITextFields, you will need to make this method return YES for the other field. For example, something like:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == countryTextField)
return NO;
return YES;
}
Hopefully this should stop the keyboard being displayed - and now you have to work out how to fire your own subviews, which I'd suggest doing via an IBAction (touch up or something perhaps). You'll have to test various things out here, but remember you're kinda corrupting the point of UITextField and maybe it'll work and maybe it won't, and maybe it'll break in the next iOS upgrade.
Okay, so first, I think you shouldn't be using a UITextField. I think you should be using a UIButton and have the current value showing as the button's title. However, if you have your heart set on it, I would use our good friend inputView, a property on UITextField, and set that to your custom input view (which I assume is a UIPickerView or similar.)
This has the added bonus of not breaking your app horribly for blind and visually impaired users, something you should probably be aware of before you go messing about with standard behaviour.
In your method :
- (IBAction)textFieldDidBeginEditing: (UITextField *)textField
call this :
[textField becomeFirstResponder];
and apply checks for the two fields i.e., when textField is the countryCodeTextField write :
[textField resignFirstResponder];
and call your method :
[self selectCountry];
In this method display the list of country codes.
So Your code will be :
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return YES;
}
- (IBAction)textFieldDidBeginEditing: (UITextField *)textField{
[textField becomeFirstResponder];
if (textField == countryCodeTextField){
[textField resignFirstResponder];
[self selectCountry];
}
}
-(IBAction)selectCountry{
//display the list no need to do anything with the textfield.Only set text of TextField as the selected countrycode.
}

How to dismiss keyboard when using DecimalPad

I have a UITableView with a custom cell that has a TextField. I have the DecimalPad comes up, and as we all know, there is no done key. I previously had resolved this type of issue when I had a "Decimal only" textfield on a normal UIView by handling the TouchesEnded event and then checking to see if the TextField was the first responder and if so, it would then resign, but if that technique could work now then I'm not able to figure out who's TouchesEnded I should be using (The UIView that everything is presented on, the UITableView, the Cell, the CellControler, the TextField.. I think I've tried everything).
I'm hoping there's another, cleaner way of dealing with this.
Anyone?
I think David has the best idea - here is some Monotouch code to get you started. You will need to put this in the View Controller where the decimal pad is being shown:
UIView dismiss;
public override UIView InputAccessoryView
{
get
{
if (dismiss == null)
{
dismiss = new UIView(new RectangleF(0,0,320,27));
dismiss.BackgroundColor = UIColor.FromPatternImage(new UIImage("Images/accessoryBG.png"));
UIButton dismissBtn = new UIButton(new RectangleF(255, 2, 58, 23));
dismissBtn.SetBackgroundImage(new UIImage("Images/dismissKeyboard.png"), UIControlState.Normal);
dismissBtn.TouchDown += delegate {
textField.ResignFirstResponder();
};
dismiss.AddSubview(dismissBtn);
}
return dismiss;
}
}
If you're targeting iOS 4.0 or greater you can create an inputAccessoryView containing a Done button to attach to the keyboard that will dismiss the keyboard when tapped. Here is an example from the documentation on creating a simple inputAccessoryView.
You could dismiss it when the user taps on the background; I think that's the most intuitive way.
In Interface Builder, change your View's class to UIControl. This is a subclass of UIView, so your program will work the same way, but you also get the standard touch events.
From here it's simple, create a method for the Touch Down event:
[numberField resignFirstResponder]
Of course it might be slightly different with MonoTouch -- unfortunately I don't know much about it, but wanted to help.
Hopefully you can use the concept, and modify your code accordingly.
Or you may just add some gesture to your main view.
For example:
//Just initialise the gesture you want with action that dismisses your num pad
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
UISwipeGestureRecognizer *swipeToHideNumPad = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(hideNumPad:)];
swipeToHideNumPad.delegate = self;
swipeToHideNumPad.direction = UISwipeGestureRecognizerDirectionDown;
[swipeToHideNumPad setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:swipeToHideNumPad];
}
//action
- (void)hideNumPad:(UIGestureRecognizer *)gestureRecognizer
{
[self.amountTextField resignFirstResponder];
}

Restricting copy,paste option for a particular UITextfield

My UIView contains Two UITextField.I need to restrict copy,paste option for one textfield.I don't want to restrict that for another.
When i am using the following code,Both the field gets restricted from copy,paste.
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if ( [UIMenuController sharedMenuController] )
{
[UIMenuController sharedMenuController].menuVisible = NO;
}
return NO;
}
Can any one provide me the solution to solve my problem.
Create a subclass of UITextField. In that subclass, implement
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (sel_isEqual(action, #selector(copy:))) {
return NO;
}
return [super canPerformAction:action withSender:sender];
}
Then use this subclass for the field that you don't want to be able to copy in, and use a regular UITextField for the one that you can copy from.
The following prevents any string longer than 1 character to be pasted. String that is 1 character long will however get through (could be useful to some people - doesn't need subclassing).
First give your textField a delegate
myTextField.delegate = self; // OR [myTextField setDelegate:self];
Then add the following method to your ViewController
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if ( [string length] > 1) {
return NO;
}
return YES;
}
Explanantion from Apple:
This default implementation of this
method returns YES if the responder
class implements the requested action
and calls the next responder if it
does not. Subclasses may override this
method to enable menu commands based
on the current state; for example, you
would enable the Copy command if there
is a selection or disable the Paste
command if the pasteboard did not
contain data with the correct
pasteboard representation type.
So, the solution is to subclass the UITextView and return properly.
More information about the method here
I had a random idea that worked perfectly on a text view. No reason why it wouldn't work on a text field.
I added the following to the text field I wanted to restrict.
Long Press Gesture Recognizer (1 touch)
Long Press Gesture Recognizer (2 touches)
Tap Gesture Recognizer (2 taps, 1 touch)
Tap Gesture Recognizer (3 taps, 1 touch)
Tap Gesture Recognizer (1 tap, 2 touches)
Then assigned the following code to it.
- (IBAction)cancelTouch:(id)sender {
//do nothing
}
I can now still scroll through the textview but a long press or double tap now do absolutely nothing!

Can I hook into UISearchBar's Clear Button?

I've got a UISearchBar in my interface and I want to customise the behaviour of the the small clear button that appears in the search bar after some text has been entered (it's a small grey circle with a cross in it, appears on the right side of the search field).
Basically, I want it to not only clear the text of the search bar (which is the default implementation) but to also clear some other stuff from my interface, but calling one of my own methods.
I can't find anything in the docs for the UISearchBar class or the UISearchBarDelegate protocol - it doesn't look like you can directly get access to this behaviour.
The one thing I did note was that the docs explained that the delegate method:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
is called after the clear button is tapped.
I initially wrote some code in that method that checked the search bar's text property, and if it was empty, then it had been cleared and to do all my other stuff.
Two problems which this though:
Firstly, for some reason I cannot fathom, even though I tell the search bar to resignFirstResponder at the end of my method, something, somewhere is setting it back to becomeFirstResponder. Really annoying...
Secondly, if the user doesn't use the clear button, and simply deletes the text in the bar using the delete button on the keyboard, this method is fired off and their search results go away. Not good.
Any advice or pointers in the right direction would be great!
Thanks!
Found the better solution for this problem :)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if ([searchText length] == 0) {
[self performSelector:#selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
}
}
- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
}
The answer which was accepted is incorrect. This can be done, I just figured it out and posted it in another question:
UISearchbar clearButton forces the keyboard to appear
Best
I've got this code in my app. Difference is that I don't support 'live search', but instead start searching when the user touches the search button on the keyboard:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if ([searchBar.text isEqualToString:#""]) {
//Clear stuff here
}
}
Swift version handling close keyboard on clear button click :
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
}
}
func hideKeyboardWithSearchBar(bar:UISearchBar) {
bar.resignFirstResponder()
}
You could try this:
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in searchBar.subviews){
for (UITextField *tf in view.subviews) {
if ([tf isKindOfClass: [UITextField class]]) {
tf.delegate = self;
break;
}
}
}
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
// your code
return YES;
}
I would suggest using the rightView and rightViewMode methods of UITextField to create your own clear button that uses the same image. I'm assuming of course that UISearchBar will let you access the UITextField within it. I think it will.
Be aware of this from the iPhone OS Reference Library:
If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.
So you'll probably also need to disable the original clear button.
Since this comes up first, and far as I can see the question wasn't really adequately addressed, I thought I'd post my solution.
1) You need to get a reference to the textField inside the searchBar
2) You need to catch that textField's clear when it fires.
This is pretty simple. Here's one way.
a) Make sure you make your class a , since you will be using the delegate method of the textField inside the searchBar.
b) Also, connect your searchBar to an Outlet in your class. I just called mine searchBar.
c) from viewDidLoad you want to get ahold of the textField inside the searchBar. I did it like this.
UITextField *textField = [self.searchBar valueForKey:#"_searchField"];
if (textField) {
textField.delegate = self;
textField.tag = 1000;
}
Notice, I assigned a tag to that textField so that I can grab it again, and I made it a textField delegate. You could have created a property and assigned this textField to that property to grab it later, but I used a tag.
From here you just need to call the delegate method:
-(BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField.tag == 1000) {
// do something
return YES;
}
return NO;
}
That's it. Since you are referring to a private valueForKey I can't guarantee that it will not get you into trouble.
Best solution from my experience is just to put a UIButton (with clear background and no text) above the system clear button and than connect an IBAction
- (IBAction)searchCancelButtonPressed:(id)sender {
[self.searchBar resignFirstResponder];
self.searchBar.text = #"";
// some of my stuff
self.model.fastSearchText = nil;
[self.model fetchData];
[self reloadTableViewAnimated:NO];
}
Wasn't able to find a solution here that didn't use a private API or wasn't upgrade proof incase Apple changes the view structure of the UISearchBar. Here is what I wrote that works:
- (void)viewDidLoad {
[super viewDidLoad];
UITextField* textfield = [self findTextFieldInside:self.searchBar];
[textfield setDelegate:self];
}
- (UITextField*)findTextFieldInside:(id)mainView {
for (id view in [mainView subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
return view;
}
id subview = [self findTextFieldInside:view];
if (subview != nil) {
return subview;
}
}
return nil;
}
Then implement the UITextFieldDelegate protocol into your class and overwrite the textFieldShouldClear: method.
- (BOOL)textFieldShouldClear:(UITextField*)textField {
// Put your code in here.
return YES;
}
Edit: Setting the delegate on the textfield of a search bar in iOS8 will produce a crash. However it looks like the searchBar:textDidChange: method will get called on iOS8 on clear.