iPhone: How can I make a UITextField invisible but still clickable? - iphone

What I'm trying to do:
In a simple UITableView, I've got a form with both text and dates/times that can be edited. I'm using UITextFields in the date/time cells too, so that the inputView property can be used to display a datePicker over the keyboard.
What the problem is:
The problem with this is that these UITextFields are really just dummy fields that show a datePicker when selected. When they're selected, they show this annoying blue cursor that blinks - but these are just dummy text fields, and I don't want them to become visible at all.
If I set alpha = 0 or hidden = YES, then the textField no longer is clickable.
Any ideas of a way around this - or, a different solution to my initial problem? Thanks

I finally figured out a way around it. By hiding the UITextView, no touches are detected. However if I overlay a custom UIButton (which can be invisible) then I can activate the UITextField when the button is touched via
[myTextField becomeFirstResponder];
and then the datePicker will replace the keyboard just like it should.

I would use a UILabel with a UItapGestureRecognizer to know when the user taps on the label.
The text field control should only be used when actual text input is necessary.
Tell me if you need more help with the gesture recognizer, they are very easy to use and save you a lot of trouble.

To use the text field's "inputView" property, overlay your textfield on top of a label. Then simply hide and show the textfield from the textFieldDid* methods, but show the actual display value in the label.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
[cell.contentView addSubview:myLabel];
[cell.contentView addSubview:myTextField];
....
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField == self.myTextField) {
[textField setHidden:YES];
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField == self.myTextField) {
[textField setHidden:NO];
}
}
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
self.myLabel.text = #"Set value here";
}

See my answer here:
Disable blinking cursor in a UITextField
That will hide the cursor and give you the option of whether or not to display anything to the user.

Related

UIPickerView multi selection on ios7

I need a picker view witch i can select multi values, like the "select input" in HTML :
In ios6, i did it with a custom view created in the UIPickerViewDelegate (pickerView:viewForRow:forComponent:reusingView:) and a UIButton in each row, but since ios7, the custom view don't received the touch event.
Is it possible to do it in ios7 ?
DrDisc has confirmed that it is not possible to handle a touch event directly from a row view since ios7.
But it is possible to :
add a Tap Gesture to the UIPickerView
retrive the selected view
call a method to check / uncheck the row
int row = [self.pickerView selectedRowInComponent:0];
UIView *rowView = [self.pickerView viewForRow:row forComponent:0];
if([rowView isKindOfClass:[YouCustomView class]])
{
[(YouCustomView*)rowView toggleCheck];
[self.pickerView reloadAllComponents];
}
I think it is more natural than a button to check/uncheck, but we lost the ability to select an other row with a tap on it.
As far as I know, this is not possible. One option is to utilize UIPickerView's delegate method:
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
You could store the selection in an array and change the text passed through from the data source to some sort of selection text ("x Selection 1").
Alternatively, you could have a 'select item' button that would add the currently displayed value to the selected array.
When the user clicks a button you can then look through the selected array for those that were selected.
These may not be the best methods, they're just my initial thoughts on it.

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 determine which section header in UITableView is being edited

I have a UITextField in a custom section header. There are multiple sections using this style of header, and therefore multiple UITextFields.
I have implemented the UITextFieldDelegate. When I edit one of these UITextFields, it calls the delegate method textFieldDidEndEditing. How do I determine which section header this UITextField was in? I need to save the value to core data in the appropriate NSManagedObject for that section.
Many thanks in advance
EDIT: Several people have suggested using a tag of the section number when creating the cell, which would work perfectly. However, I have already assigned the UITextField a tag to distinguish it as a 'header' textfield as opposed to a cell textfield or a 'footer' textfield. There are a whole lotta textfields on this table!!
Further EDIT: Using in indexPath has been suggested. This would be my preferred solution if I can get it to work. Does anyone know if headers and footers have indexPaths?
You could use tags to identify UITextField instances. Since you're already setting tags in UITextField instances, set the tags on the section views itself:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *sectionView = ... // your section view instance
// assign the section index as the tag
sectionView.tag = section;
return sectionView;
}
In the textfield delegate, get the section index from the sender's parent:
- (void) textFieldDidEndEditing:(UITextField *)textField;
{
NSInteger theSectionIndex = textField.superview.tag;
// your custom logic here
}
You would probably want to look into UITableView method indexPathForCell:.
You can get the cell through view hierarchy from your UITextField, since it's in your Cell's contentView.
Regards,
sven.
It is very simple Mr.Ben Thompson. You have named different between each one to UITextFields am i right?. Just find the specific UITextField by used it's name.
-(void) textFieldDidEndEditing:(UITextField *)textField
{
if (textField == textfieldOne)
{
//Do whatever you want...
}
else if (textField == textfieldTwo)
{
//Do whatever you want...
}
else if (textField == textfieldThree)
{
//Do whatever you want...
}
}
I hope it will help you a little bit. Thanks.
i believe you add the field as a custom view to the header in viewForHeader method of tableview.
I suggest keeping a tag of the field using the section like this.
textfield.tag == section;
then in the delegate message you can have a switch method to compare tags..and do your own code there

Simulate Tab Key Press in iOS SDK

When a hardware keyboard is used with iOS, pressing tab or shift-tab automatically navigates to the next or previous logical responder, respectively. Is there a way to do the same programmatically (i.e. simulating the tab key rather than keeping track of the logical order manually)?
As William Niu is right but you can also use this code explained below.
I have used this and got success.Now consider the example of UITextField...
You can use UITextView's delegate method -(BOOL)textFieldShouldReturn:(UITextField*)textField as explained below.
But before doing this you should have to give tag to each UITextField in an Increment order...(Increment order is not required necessary ,but as for my code it is required, you can also use decrement order but some code changes for doing this)
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSInteger nextTag = textField.tag + 1;
UIResponder* nextResponder = [self.view viewWithTag:nextTag];
if (nextResponder) {
[nextResponder becomeFirstResponder];
} else {
[textField resignFirstResponder];
}
return YES;
}
Hope this will work for you...
Happy coding....
You may define the "tab-order" using the tag property. The following post describes how to find the next tag index to go to for UITextFields,
How to navigate through textfields (Next / Done Buttons).
Here is a modified version of the code from that post. Instead of removing keyboard at the last tag index, this following code would try to loop back to the first tag index.
-(BOOL)textFieldShouldReturn:(UITextField*)textField;
{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
return NO;
}
// Try to find the first responder instead...
// Assuming the first tag index is 1
UIResponder* firstResponder = [textField.superview viewWithTag:1];
if (firstResponder) {
// loop back to the first responder
[firstResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
If you want an UI element other than UITextField, you should still be able to use the same logic, with a few more checks.
Not sure if this helps, but in the context of a UITextFields, if you implement UITextFieldDelegate, - (BOOL)textFieldShouldReturn:(UITextField *)textField will get called when the return key of the soft keyboard is pressed.
I've tried to hit directly on my laptop keyboard and it seemed to jump between all the textfields in the order in which you've added them to the view, but didn't go to any other types of fields (Buttons etc.).
key on the keyboard is simulating the key on the soft keyboard of the simulator, which works as expected.

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.