I would like a text similar to Twitter's
I am currently using a UITextView since it has multi-line support. I kind of figured out how to use a label that counts the characters and keeps the user up to date of any characters added or removed.
Empty:
With Text:
The problem I am having however is when I copy or paste any text in the view, (like if I highlight all the text, as in the second picture) and I delete it, the counter will not update. Or if I paste any text, the count just decrements one character, though the text field limit still stays correct, just the counter is no longer in sync with it.
Code: http://pastebin.com/UK91Ccbb
There is a delegate method for UITextView as
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
it is called every time a character is inserted into the UITextView. In this method set the length of text in your counter UILabel as follows
counterlabel.text = [NSString stringWithFormat:#"%i", textView.text.length];
return YES at the end of method if the length is within range i.e. less than or equal to 140 else return NO.
UPDATE:..
To restrict to 140 characters.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
return textView.text.length <= 140;
}
To handle text removal on selection and counting characters.
- (void)textViewDidChange:(UITextView *)textView
{
count.text = [NSString stringWithFormat:#"%i", (140- textView.text.length)];
}
NSLog(#"You added a character");
charactersLeft--;
I think the problem here is that you should have written:
charactersLeft -= text.length;
In viewDidLoad :
charactersLeft = 140;
characterCountLabel.text = [NSString stringWithFormat:#"%d",charactersLeft];
Now use this it works well :
- (void)textViewDidChange:(UITextView *)textView{
NSString *textString = textView.text;
int chars = [textString length];
if (chars <= 140) {
[characterCountLabel setText:[NSString stringWithFormat:#"%d",(140 - chars)]];
}
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
[textView resignFirstResponder];
if (textView.text.length == 140 && [text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
}
else if ((textView.text.length) >= 140 && range.length == 0){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"You have exceeded the characters limit." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
return NO; // return NO to not change text
}
return YES;
}
Note that here I have used returnType key to resign the keyboard.You may change it to work as usual.
Related
Which count maximum char's in UITextField and UITextView? It is really interesting for me! I have some textfields and textviews. And if I don't set max value for it, then which count char's can be in it?
You need to implement UITextFieldDelegate and UITextViewDelegate Method to get the count of characters
Try this code
For UITextView's
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSUInteger enteredTextLength; // Variable to store the length on entered string.
if(textView == txtViewName) {
enteredTextLength = [textView.text length] + [text length] - range.length;
NSLog(#"Text Length = %d", enteredTextLength);
// To check number of characters entered.
if (enteredTextLength < 10) {
return YES;
}
else {
return NO;
}
}
else {
return YES;
}
}
For UITextField's
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger enteredTextLength; // Variable to store the length on entered string.
if(textField == txtAlpha) {
enteredTextLength = [textField.text length] + [string length] - range.length;
NSLog(#"Text Length = %d", enteredTextLength);
// To check number of characters entered.
if (enteredTextLength < 10) {
return YES;
}
else {
return NO;
}
}
else {
return YES;
}
}
I've run into a couple of topics that discuss an input box using NSAlert like the following.
- (NSString *)input: (NSString *)prompt defaultValue: (NSString *)defaultValue {
NSAlert *alert = [NSAlert alertWithMessageText: prompt
defaultButton:#"OK"
alternateButton:#"Cancel"
otherButton:nil
informativeTextWithFormat:#""];
NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
[input setStringValue:defaultValue];
[alert setAccessoryView:input];
NSInteger button = [alert runModal];
if (button == NSAlertDefaultReturn) {
[input validateEditing];
return [input stringValue];
} else if (button == NSAlertAlternateReturn) {
return nil;
} else {
return nil;
}
}
So you can insert a textbox just like you do with AlertView in iOS. But how can you validate the text field value to enable and disable the default button? iOS has (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView to let you validate the input.
Thank you.
set
input.delegate=self;
and then implement the following methods
(void)controlTextDidChange:(NSNotification *)notification
(void)controlTextDidEndEditing:(NSNotification *)notification
you can validate here
Hello everyone,
I am working on a project where requirement is keypad should not pop up when we clicked on the text field as we are making number pad for the particular text field and we have succeed for doing this by..
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == dateFld) {
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
textField.inputView = dummyView;
}
}
Now my problem is, I want to validate that text field to accept only particular format and limited number of input but i am unable to do this because the method for that is not getting called when we disabled the keypad to pop below is my code to validate the textfield.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Format Date of Birth YYYY-MM-DD
if(textField == dateFld)
{
if ((dateFld.text.length == 4)||(dateFld.text.length == 7))
//Handle backspace being pressed
if (![string isEqualToString:#""])
dateFld.text = [dateFld.text stringByAppendingString:#"-"];
return !([textField.text length]>9 && [string length] > range.length);
}
else
return YES;
}
Please help me to over come from this problem or any other way to do this.
Thanks
I want to validate that text field to accept only particular format and limited number of input :
if(textField == dateFld){
NSCharacterSet* numberCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789+"];
for (int i = 0; i < [string length]; ++i)
{
unichar c = [string characterAtIndex:i];
if (![numberCharSet characterIsMember:c])
{
return NO;
}
}
//Format Date of Birth YYYY-MM-DD
if([textField.text length] == 4) {
textField.text=[NSString stringWithFormat:#"%#-",textField.text];
}else if([textField.text length]==6){
textField.text=[NSString stringWithFormat:#"%#-",textField.text];
}else if([textField.text length]==8){
textField.text=[NSString stringWithFormat:#"%#",textField.text];
}
NSLog(#"value %#",textField.text);
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 13) ? NO : YES;
}
}
It's working fine for me.
I would do something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSError *_error = nil;
NSRegularExpression *_regularExpression = [NSRegularExpression regularExpressionWithPattern:#"^\\d{0,4}-{0,1}$|^\\d{4}-{1}\\d{0,2}-{0,1}$|^\\d{4}-{1}\\d{2}-{1}\\d{0,2}$" options:NSRegularExpressionCaseInsensitive error:&_error];
NSMutableString *_newText = [NSMutableString stringWithString:textField.text];
[_newText insertString:string atIndex:range.location];
NSArray *_matches = [_regularExpression matchesInString:_newText options:0 range:NSMakeRange(0, _newText.length)];
return _matches.count > 0;
}
EDIT#1 (on 22/01/13)
of course, your class has to be a delegate class of your UITextField, otherwise the method above will be never called back.
there are some additional steps how you can do it.
in the YourViewController.h file:
#interface YourViewController : UIViewController <UITextFieldDelegate> {
// ...
}
#property (nonatomic, strong) IBOutlet UITextField *myTextField; // is case of ARC and iOS5+
#end
in your YourViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
// ...
[self.myTextField setDelegate:self]; // you can do the same thing in the interface builder as well.
}
You need to validate the inputs in your dummyView
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
textField.inputView = dummyView;
since you replaced the input view of UITextField, UITextField delegates will not be called.
I have followed the first steps tutorial from apple, and I have a working app that can read text and display it in a label on button click. When I hit enter the textfield is resigned and the keyboard disappears, and when I hit the button the changeGreeting method is invoked. I want to call the changeGreeting function in the function thats used when I hit enter which is textFieldShouldReturn.
I tried everything I could think of, and read a lot online but Im not sure how to deal with (id)sender as a param for example. How should I edit my code to call changeGreeting on textfield enter?
code below:
- (IBAction)changeGreeting:(id)sender {
self.userName = self.textField.text;
NSString *nameString = self.userName;
NSString *endString = #"burp";
int r = arc4random() % 74;
if ([nameString length] == 0) {
nameString = #"World";
}
NSString *greeting = [[NSString alloc] initWithFormat:#"Hello, %#, %#! Random String of numbers: %d", nameString, endString, r];
self.label.text = greeting;
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
// on enter the keyboard is removed, but I want the
// changeGreeting method involed too, something like
// [self changeGreeting]
}
return YES;
}
thanks in adv
You already have it. Just ignore the sender parameter:
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
// on enter the keyboard is removed, but I want the
// changeGreeting method involed too, something like
[self changeGreeting:nil]
}
This is what I want the app to do.
Tap in a "Text View" not a "Text Field", then the keyboard is displayed and a bullet point ("\u2022") pops up. You type your sentence, and when you hit return it makes a new bullet.
So essentially, you have a Text View that is a bulleted list. Much like Word, where you start a bullet and when you hit return it make a new bullet for you, so you can start typing on that line.
How do I do this?
This is what worked for any other stupid noobs like me:
I put this into my .m file
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
{
NSString *modifiedString = [myTextView.text stringByAppendingString:#"\n\u2022"];
[myTextView setText:modifiedString];
return NO;
}
return YES;
}
I put this into my .h file
#interface CRHViewController3 : UIViewController <UITextViewDelegate> {
__weak IBOutlet UITextView *myTextView;
}
and then I put this under my viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
[myTextView setDelegate:self];
}
Try out this.
(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:"\n"])
{
NSString *modifiedString = [textView.text stringByAppendingString:#"\n\u2022"];
[textView setText:modifiedString];
return NO;
}
return YES;
}
The method -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text would be called for each letter entered on deleted.
So in this method you could try to replace all line breaks with bullet char.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
...
textView.text = [textView.text stringByReplacingOccurrencesOfString:#"\\n" withString:#"\u2022"];
...
}
To use this code:
(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:"\n"])
{
NSString *modifiedString = [textView.text stringByAppendingString:#"\n\u2022"];
[textView setText:modifiedString];
return NO;
}
return YES;
}
Your header file must look like this:
#interface MyViewController : UIViewController <UITextViewDelegate> {
//instance variables in here
}