I can't seem to find any information on what should be a simple issue. I have a table which contains a series of cells. When you tap on the cell it shows the information of that object in detail. I know it is possible to have a button which places all of the data on the screen in EDIT mode. Any tutorials or advice as how to do this (properly/ with best practices)?
Just to be clear this is for iPhone/ Objective-C/ Cocoa.
Thanks,
EDIT 1
Sorry. I know how to put the button there. But how do make the labels editable?
You are confusing two states:
Putting the tableView into editing mode - this is for deleting, or moving cells around in the table, regardless of the cell content. This is controlled by the UITableView.editing property.
and
Putting the tableViewCell into some sort of editing state. There is no official editing state for the cell (i.e. there is no single flag to set to make all UILabels in a cell into editable textFields.) You need to implement all of this logic yourself. If you're using .xibs, a good practice here is to have a different .xib for your cell's editing mode.
You cannot have editable labels. However, you can replace the label with a textfield when the button is pressed, and then update the label once finished.
One way to do this is the following. Create a textfield in the same location as the label and initially set textField.hidden = YES;. Then implement something along these lines:
-(IBAction)editMyCell:(id)sender {
textField.text = cellLabel.text;
cellLabel.hidden = YES;
textField.hidden = NO;
[textField becomeFirstResponder];
}
and when the editing has finished, restore with
-(void)textFieldDidEndEditing:(UITextField *)textField {
cellLabel.text = textField.text;
textField.hidden = YES;
cellLabel.hidden = NO;
[textField resignFirstResponder];
}
You'll probably want to tweak this idea a bit for your situation, but it's probably the simplest thing to implement that achieves what you're after.
There is nothing in the base sdk associated with editing a UIViewController. Normally that kind of logic is defined by the programmer. But I could see someone writing a function that turns all of your UILabels in your UIView into UITextViews so the user can edit the text.
There might be sample code out there but this seems like custom code to me.
Related
I'm currently developing a Swift/Cocoa application with XCode 12.3 and Swift 5.
I'd like to manipulate the design of the close button in the titlebar of a NSWindow.
I've already tried to change the design using
self.window?.standardWindowButton(.closeButton)?.layer. ... = ...
But this approach seems not to be working - at least for me. Do you have any ideas on how to make it possible?
You need to set wantsLayer to true. Standard window buttons are regular NSButtons with an NSCell inside them. To customize the and not have the original button block the view, you either need to remove the cell and use the layer or just create a custom one.
Note that when removing or setting your own button cell, its action selector will reset, so you need to keep sure that the buttons still do what you want them to.
Here's the code in Objective C, but it should be easy enough to translate into Swift:
NSButton *button = [self standardWindowButton:NSWindowCloseButton];
button.wantsLayer = YES;
button.layer.backgroundColor = NSColor.greenColor.CGColor;
NSCell *cell = [[NSCell alloc] initTextCell:#"?"];
[button setCell:cell];
Result:
I have used the demonstration code Apple has in their docs here:
http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html#//apple_ref/doc/uid/TP40009542-CH5-SW7
To have my view move accordingly depending on which textField is being edited. It works great, my view moves as I expect, except for one thing.
My issue is, I can select a textField and it will only move the view up when I begin typing and not when I actually select the textField.
I am literally using identical code as in the docs (follow the link above). Quite frustrating, I can't see what would cause this. Thanks.
Here is The Logic See.
1)You need a Flag Value Set TRUE initially in ViewDidLoad or viewWillAPpear.
suppose isNeedToMove is that Flag value.
you need to Implement these methods in Your Code,for using them don't forget to Adopt the protocol UITextFieldDelegate in your UIViewcontroller.h class.
EDIT:Here I have Chnaged The Code AS you mentioned in yOur Comment You needed to move That UIView on just Touching the TextFIeld.See Here below Is The Logic With SOme Code.
addTarget To the TextField in ViewDiodiLoad
- (void)viewDidload
{
[touchyTextField addTarget:self
action:#selector(yourDesiredMethod)
forControlEvents:UIControlEventTouchDown];
}
-(void)yourDesiredMethod
{
if(isNeedToMove)//this Flag Avoid The unnecessary move call.
{
//here call the method which Move The UIview
}
}
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
[textField resignFirstResponder];
//here call the method which move UIView to its actual position.
isNeedToMove= TRUE;
return YES;
}
I hope you may get Some idea .
I had this trouble too. In keyboardWasShown, the Apple documentation says:
if (!CGRectContainsPoint(aRect, activeField.frame.origin)
I used:
if (activeField == myTextField)
Here's the long version of the answer: moving content located under the keyboard
Is there any way to hide the keyboard when a clear button of UITextField is pressed?
Yes, there is, although I suspect that doing so would violate the Apple Human Interface Guidelines.
To do so, add the following method to your view controller's implementation file. Then make the view controller into your textfield's delegate.
- (BOOL) textFieldShouldClear:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
The downside to this approach is if you ever want to prevent the textfield from clearing, your code becomes messy. Instead you might try to define a custom method and then connect it to the valueDidChange method and check for an empty value.
-(IBAction)hideKeyboardFromTextField:(id)sender{
//TODO: Check if the previous value was longer than one character to differentiate
//between backspace and clear.
//check if the editing caused the box to be empty
if([[sender value] isEqualToString:#""] || [sender value] == nil)
[sender resignFirstResponder];
}
}
The problem here is that you can't easily differentiate between a tap on the clear button and a tap on the delete button when there is one character in the UITextField.
As I said in the beginning of my answer, this is not advisable in the first place and as the answers here have shown, it is not so easy to implement. I don't think it's worth the hassle, considering the difficulty involved and the fact that it doesn't result in optimal user experience.
This code is definitely working for me to hide the key board while clearing out the content of the textfield
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
textField.text = #"";
return NO;
}
Yep. Call resignFirstResponder on the text field in the delegate's textFieldShouldClear: method.
In UITextFieldDelegate
- (BOOL)textFieldShouldClear:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
But there is a problem with this. From the manual, "The text field calls this method in response to the user pressing the built-in clear button. (This button is not shown by default but can be enabled by changing the value in the clearButtonMode property of the text field.) This method is also called when editing begins and the clearsOnBeginEditing property of the text field is set to YES."
Note that, this method is called when editing begins if clearsOnBeginEditing is set to YES. So if you call resignFirstResponder in this method then editing will not begin actually. So you need to set clearsOnBeginEditing to NO. Obviously then the text field won't be cleared when editing begins.
Another IMPORTANT matter not directly related to the question. Hiding the keypad after tapping clear button is not a familiar behavior and Apple does NOT like changing the behavior of standard items. You may get a rejection for this.
Try this code:
[TextField performSelector:#selector(resignFirstResponder) withObject:nil afterDelay:0.1];
For Swift
In your UITextFieldDelegate
func textFieldShouldClear(_ textField: UITextField) -> Bool {
textField.resignFirstResponse()
return true
}
I have a table and in one of the cells I keep a UITextView. When the user taps it the keyboard appears. I was trying various ways to get rid of it. My first approach was to detect a tap on the table cell of the UITextView, but since the text view takes most of it, it's not suitable. Then I tried to add a button to the toolbar and whenever the user presses it, the keybord disappears with resignFirstResponder, but it won't work. It seems that only when I'm in the same view as the UITextView resignFirstResponder works. So how can I get rid of the keyboard from a different view?
Thanks.
The method below uses the Return Key to dismiss the UITextView Keyboard.
In your Controller, set the UITextView's Delegate to self
like this:
myTextView.delegate=self;
Then add this method:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:#"\n"]) {
// Be sure to test for equality using the "isEqualToString" message
[textView resignFirstResponder];
// Return FALSE so that the final '\n' character doesn't get added
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
This should work if you're not using the Return key as a true Return key (e.g. adding new line).
What do you mean "it won't work". If txtView is your UITe4xtView, do you mean that associating the button with an action that has [txtView resignFirstResponder] wont work? I've used this code before and it works for me
Without knowing the size of the controls, nor the intent, it's a bit hard to make a solid recommendation. However, if you're looking for a read-only text view, why not consider a UILabel? If it's going to contain a great deal of read-only text and you need rich formatting, consider a UIWebView with your formatting.
Of course, this answer could be completely inappropriate. Can you clarify your intentions, maybe show a screen shot of the app-in-progress (untapped, of course)?
try unchecking the 'Editable' option in the Text View Attributes window in Interface Builder.
this stops the keyboard from showing up if the user clicks on your TextView
i've use for that kind of problem, the folowing method
- (BOOL)textFieldShouldReturn: tf_some_text_field {
[tf_some_text_field resignFirstResponder];
[tf_another_text_field_in_the_same_view resignFirstResponder];
return YES;
}
hope it helps...
I have a text field entry in my view that I would like to block access to during a background operation. I've tried using the editable property, which successfully blocks access during the background operation, but the moment I set editable to YES, the keyboard comes up and the textfield becomes the first responder. Dismissing the keyboard just after changing editable doesn't do anything:
// Broken code
textView.editable = YES;
[textView resignFirstResponder];
I've thought about adding a clear UIView that just blocks access to the UITextView after dismissing the keyboard, but that seems like overkill. Is there a correct way to handle this?
Just so people don't have to read farther than the selected answer: It turns out that this is a "known issue" in the SDK, and you can find it listed in the release notes. Using userInteractionEnabled performs the same function, as long as you make sure to dismiss the keyboard yourself.
Try textView.userInteractionEnabled = NO;
Put a UIView in front of the UITextView with a dark (or white) background color and alpha set low (like 5%) sized to fully cover the textview. Default it to hidden.
When you want the textinput disabled, send it a resignFirstResponder then show the hidden layer on top. It intercepts user inputs (and ignores it). The alpha color will make it look 'dimmed.' Once your background operation is done just set the cover view to hidden and you're good to go. If you want to get fancy you can do UIView alpha fade animations.
I'm not sure of a "correct way" but I'd probably do the transparent view solution... I agree that it seems like overkill but the simple solution is often a good answer.
Since the view gets focus upon changing the editable properties this would be easier.
the other solution that I can think of is to derive a custom UITextView and recode the editable property (or make a new method) that can accomplish what you are trying to do. This is a good object oriented solution but this could be come cumbersome.
You might also consider using a Category to add the functionality. But for either of these solutions, are still back to square one of how to accomplish what you need...
Thank god someone came up with a better response. I originally built it with the following blocker, but the userInteractionEnabled BOOL is much easier.
It turns out that the problem is a known issue with UITextView. My workaround:
#import <UIKit/UIKit.h>
/**
God damn SDK bug means that you can't use editable to enable/disable a
UITextView (It brings up the keyboard when re-enabling)
*/
#interface StupidF_ingTextViewBlocker : UIView {
}
#end
#implementation StupidF_ingTextViewBlocker
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
self.backgroundColor = [UIColor clearColor];
self.opaque = NO;
}
return self;
}
- (void)dealloc {
[super dealloc];
}
#end
Then in place of the code I've placed above (instead of using editable). To disable (assuming I have an iVar called blocker):
// Put this in a lazy loading property or in loadView
blocker = [[StupidF_ingTextViewBlocker alloc] initWithFrame:writeView.frame];
// The blocker code ~= textView.editable = NO
[self.view addSubview:blocker];
// Removing the blocker ~= textView.editable = YES
[blocker removeFromSuperView];
Subclass UITextView, and implement a single method:
- (BOOL) canBecomeFirstResponder { return NO; }
Use the UITextViewDelegate. You'll need to swap out the delegate object depending on the current state.
If in the blocked state, then you'll use a delegate where textViewShouldBeginEditing returns NO.
the other delegate's textViewShouldBeginEditing would return YES.