UILabels not overlaying correctly in UITextView - iphone

I'm trying to add syntax highlighting to my program.I'm using this code to add highlights:
-(void)highlightWord:(NSString *)word: (UIColor *)color {
int amount = textDisplay.text.length;
NSString *newString = textDisplay.text;
NSUInteger count = 0, length = amount;
NSRange range = NSMakeRange(0, length);
while(range.location != NSNotFound)
{
range = [textDisplay.text rangeOfString: word options:NSLiteralSearch range:range];
if(range.location != NSNotFound)
{
range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
count++;
}
}
while (count != 0) {
count--;
NSRange highlight = [newString rangeOfString:word];
newString = [textDisplay.text stringByReplacingCharactersInRange:highlight withString:#" "];
UILabel *view1 = [[UILabel alloc] initWithFrame:[self frameOfTextRange:highlight inTextView:textDisplay]];
view1.text = word;
view1.textColor = color;
view1.font = [UIFont fontWithName:#"System" size: 14.0];
view1.backgroundColor = [UIColor clearColor];
view1.textAlignment = UITextAlignmentLeft;
[textDisplay addSubview:view1];
}
}
- (IBAction)highlighString:(id)sender {
for (UIView *subview in [textDisplay subviews]){
if ([subview isKindOfClass:[UILabel class]]){
[subview removeFromSuperview];
}
}
[self highlightWord:#"test" :[UIColor blueColor]];
[self highlightWord:#"this" :[UIColor redColor]];
[self highlightWord:#"is" :[UIColor grayColor]];
[self highlightWord:#"a" :[UIColor greenColor]];
}
#end
But this seems to cause a weird results:
The desired result would be that it overlays to colored label seamlessly.

Mixing UILabel and UITextView is unlikely to give you easy copy and paste. It's an interesting idea, but I'd be surprised if it worked seamlessly. The usual Apple solution for this problem in all non-beta versions of iOS is to use a UIWebView, horrible as that is. Cocoanetics has one called DTRichTextEditor which I haven't reviewed, but based on the quality of their work on DTCoreText (which I'm very impressed with), I have high hopes for it for iOS 5. Betas are under NDA, but you may be interested in watching Session 220 from WWDC 2012 for more future-looking information.
Your specific bug is that you're adding the labels as subviews to the text view. You should put them on top of the text view as peers. Putting them inside the textview makes you subject the text view's drawing system, which is biting you. Of course when you put them on top of the text view, that's going to make it hard to handle copy and paste. You'll need to pass the touches through somehow, and then draw the selection correctly. See the previous paragraph.
If a fully editable rich-text view were easy to hack up with some labels, then you'd find several implementations on GitHub. Unfortunately it's actually pretty tough to do well. I bow to Cocoanetics for taking it on; I gave up pretty quickly. If you can simplify your problem to a non-general text view, then it may be possible this way, but I'd recommend investigating DTRichTextEditor or a UIWebView. See Session 511 "Rich Text Editing in Safari on iOS" from WWDC 2011.

Related

Remove dot from UITextField

I create on application and i required to enter price. client required its own design keyboard so i develop following keyboard. it works perfect . Problem is when the text is larger then UITextField's with then it display dots. I search on google and SO but not found any thing.
how to avoid dots next to a uitextfield
How to remove dots in UITextfield? and other answer but not working in my case. When I used default keyboard it scroll the text what i input number
My key board is
when length is greater then TextFied Width then it display
My code is
- (IBAction)numberPressed:(id)sender {
UIButton *btn=(UIButton *)sender;
int number=btn.tag;
if (number <= 9)
txtPrice.text = [NSString stringWithFormat:#"%#%d",txtPrice.text, number];
//decimal point
else if (number == 10) {
if ([txtPrice.text rangeOfString:#"."].location == NSNotFound)
txtPrice.text = [NSString stringWithFormat:#"%#.", txtPrice.text];
}
//0
else if (number == 11)
txtPrice.text = [NSString stringWithFormat:#"%#0", txtPrice.text];
//backspace
else if (number == 12) {
if ([txtPrice.text length] > 0)
txtPrice.text = [txtPrice.text substringToIndex:[txtPrice.text length] - 1];
else
txtPrice.text = #"";
}
}
#pragma mark -
#pragma mark -TextField Delegate Method
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[self showKeyboard];
return NO; // Hide both keyboard and blinking cursor.
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
return YES;
}
UITextField is specifically one-line only. So whatever the UITextField is big when it reach the end it will display dots.
You need to use UITextView instead of UITextField for display and editing of multiline text.
In Interface Builder add a UITextView where you want it and select the "editable" box. It will be multiline by default.
I think this will help you. ^_^
You can try this:
self.txtPrice.font = [UIFont systemFontOfSize: 14.0];
self.txtPrice.adjustsFontSizeToFitWidth = YES;
self.txtPrice.minimumFontSize = 7.0;
"adjustsFontSizeToFitWidth" is a Boolean value indicating whether the font size should be reduced in order to fit the text string into the text field’s bounding rectangle.
"minimumFontSize" is the size of the smallest permissible font with which to draw the text field’s text.
If you want a similar behavior as the calculator or the phone app you have to set the following property to true(YES):
textField.adjustsFontSizeToFitWidth = YES;
You should also set the minimumFontSize property to "to prevent the receiver from reducing the font size to the point where it is no longer legible."
Check out the UITextField Reference
Another approach is (Remove dot and clip text to frame)-
your can remove dot from UITextField calling following code
[self.yourTextField becomeFirstResponder];
you can also hide default keyboard [if you use any custom keyboard] using following code
// Hide keyboard for Dial Pad, but show blinking cursor
UIView *dummyKeyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
yourTextField.inputView = dummyKeyboardView;
[dummyKeyboardView release];
But I think IlNero's answer is better for you if you want to show all text (does not clip).
What you can do is
txtPrice.text = [txtPrice.text stringByReplacingOccurrencesOfString:#"." withString:#""];
let me know it is working or not!!!
Happy Coding!!!

Is it possible to highlight a NSString or draw some color to a string

i am having this code to get the text between "." for example i am having lots of text like .1 this is first.2 this is second.3 this is fourth etc etc.when i tap the first ext it displays the first text in log .the code is
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[NSTimer scheduledTimerWithTimeInterval:0.001 target:maintextview selector:#selector(resignFirstResponder) userInfo:nil repeats:NO];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
NSRange selectedRange = [textView selectedRange];
NSString *backString = [maintextview.text substringToIndex:selectedRange.location];
NSRange backRange = [backString rangeOfString:#"." options:NSBackwardsSearch];
NSRange backRangee = [backString rangeOfString:#"." options:NSBackwardsSearch];
int myRangeLenght = backRangee.location - backRange.location;
NSRange myStringRange = NSMakeRange (backRange.location, myRangeLenght);
NSString *forwardString = [maintextview.text substringFromIndex:backRange.location];
NSLog(#"%#",[[forwardString componentsSeparatedByString:#"."] objectAtIndex:1]);
}
forwadString contains the tapped text,i just want to highlight this string or draw a color above this text using core graphics or something like that.is out possible?
thanks in advance
Much to my and many other's disappointment, Apple chose not to implement NSAttributedString until iOS 3.2, and even then, all standard UI elements are incapable of rendering them!
Luckily, the few, the proud, and the brave have answered the call and DTCoreText was born.
As for an actual selection, because UITextView conforms to UITextInput as of iOS 3.2, you can use and set the selectedTextRange.
It's impossible to 'colour' an NSString, a string is just a representation of characters, it holds no font, colour or style properties. Instead you need to colour the UI element that draws the text to the screen.
If forwardString is in a UILabel or UITextView you can colour the text inside these by setting the textColor property. For example if you had a UILabel called lbl you could set the colour by using:
lbl.textColor = [UIColor redColor];

Adding an uneditable text suffix to a UITextField

I have a UITextField that I'd like to add a "?" suffix to all text entered.
The user should not be able to remove this "?" or add text to the right hand side of it.
What's the best way to go about this?
Use the UITextFieldDelegate protocol to alter the string whenever the field is being edited. Here's a quick stab at it; this will need work, but it should get you started.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * currentText = [textField text];
if( [currentText characterAtIndex:[currentText length] - 1] != '?' ){
NSMutableString * newText = [NSMutableString stringWithString:currentText];
[newText replaceCharactersInRange:range withString:string];
[newText appendString:#"?"];
[textField setText:newText];
// We've already made the replacement
return NO;
}
// Allow the text field to handle the replacement
return YES;
}
You'll probably need to subclass UITextField and override its drawText: method to draw an additional "?" character to the right of the actual text. (Rather than actually add a "?" to the text of the view.
I had this issue and I wrote a subclass to add this functionality: https://github.com/sbaumgarten/UIPlaceholderSuffixField.
Hopefully you have found a solution by now but if you haven't, this should work.
I realize this answer is late, but I found most of these did not work for my scenario. I have a UITextField that I simply want to force to have a suffix that the user cannot edit. However, I don't want to subclass UITextView, modify how it handles drawing, etc. I just want to prevent the user from modifying the suffix.
First, I ensure the suffix is set in the textfield when editing takes place. This could be done any number of ways depending upon your scenario. For mine, I wanted it there from the start, so I simply set the textfield's text property equal to the suffix when the view loads and store off the length of the suffix for later. For example:
- (void)viewDidLoad {
[super viewDidLoad];
myTextField.text = "suffix";
_suffixLength = myTextField.text.length;
}
Then I used the UITextFieldDelegate protocol as Josh suggested above, but use the length of the string and the range to ensure nothing edits the suffix:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Determine starting location of the suffix in the current string
int suffixLocation = textField.text.length - _suffixLength;
// Do not allow replacing anything in/past the suffix
if (range.location + range.length > suffixLocation)
{
return NO;
}
// Continue with delegate code...
}
This should work for any suffix value you assign to the textfield.
For a single-line UITextField you should be able to measure the size of the NSString (it has a measurement function in there, somewhere) and move a UILabel to the right position.
I would add a method that is called when edit finishes:
`- (void)editDidFinish {
NSString* str=[[NSString alloc] init];
str=myEdit.text;
[str stringByAppendingString:#"?"];
myEdit.text=str;
}`
OK, im definitly too late, but maybe i can help someone out either way:
The intended way to accomplish this is by using a custom NSFormatter. Heres the docs:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFormatter_Class/Reference/Reference.html
The basic idea is this: you create a subclass of NSFormatter, and the override at least the two worker methods:
-stringObjectForValue:
this will produce the dipsplay-String from the value stored in the object (i.e. add your questionmark here)
-objectValue:ForString:errorDescription
here, you need to transform the display-string into an object you want to store, i.e. remove the questionmark
The formatter can then be used to convert the data from the stored objects into strings that are suitable for presentation to the user.
The big advantage is that you can use formatters wherever your string will appear in the UI. It is not limited to certain UI-Elements like the solution where you override -drawText in UITextField. Its just hella convenient.
This class method I have written in Objective-C, helps you to add a suffix text to a UITextField.
I order to make it work, you need to initialize the UILabel to the prefix or suffix in your UITextFieldLabel as follow:
myTextField.rightView = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, myTextField.frame.size.height)];
myTextField.rightViewMode = UITextFieldViewModeAlways;
[MyClass UpdateUITextFieldSuffix:myTextField withString:#"My Suffix!"];
Once we have the UILabel attached to the UITextField, you can use this class method to update the text, and this text will be automatically resized to fit in the field.
+ (BOOL)UpdateUITextFieldSuffix:(UITextField*)textField withString:(NSString*)string
{
BOOL returnUpdateSuffix = NO;
if (string != nil && [string respondsToSelector:#selector(length)] && [string length] > 0)
{
NSObject *labelSuffix = textField.rightView;
if (labelSuffix != nil && [labelSuffix respondsToSelector:#selector(setText:)])
{
[(UILabel*)labelSuffix setTextAlignment:NSTextAlignmentRight];
[(UILabel*)labelSuffix setText:string];
[(UILabel*)labelSuffix setBackgroundColor:[UIColor redColor]];
{
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
((UILabel*)labelSuffix).font, NSFontAttributeName,nil];
CGRect frame = [((UILabel*)labelSuffix).text boundingRectWithSize:CGSizeMake(0.0f, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGSize size = frame.size;
CGRect newFrame = [(UILabel*)labelSuffix frame];
newFrame.size.width = size.width;
[(UILabel*)labelSuffix setFrame:newFrame];
[(UILabel*)labelSuffix setNeedsLayout];
[(UILabel*)labelSuffix layoutIfNeeded];
}
returnUpdateSuffix = YES;
}
}
return returnUpdateSuffix;
}
I have written the following method to achieve the above task of placing non-editable suffix to UITextField:
- (void)setSuffixText:(NSString *)suffix
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setBackgroundColor:[UIColor clearColor]];
[label setFont:[UIFont fontWithName:self.tfdDistance.font.fontName size:self.tfdDistance.font.pointSize]];
[label setTextColor:self.tfdDistance.textColor];
[label setAlpha:.5];
[label setText:suffix];
CGSize suffixSize = [suffix sizeWithFont:label.font];
label.frame = CGRectMake(0, 0, suffixSize.width, self.tfdDistance.frame.size.height);
[self.tfdDistance setRightView:label];
[self.tfdDistance setRightViewMode:UITextFieldViewModeAlways];
}​

iOS: Highlight spelling errors but disable suggestions?

My app implements a custom spell checker with its own window and a different workflow from the built-in spell checker in iOS. Therefore I have switched off correction in the main text input view. This disables the built-in suggestions, but also the highlighting of misspelled words.
Is there a way to keep the highlighting, but disable the suggestions?
You can use below code to check weather the printed word is correct spelled or not and if wrong then highlight that word
first import
#import <UIKit/UITextChecker.h>
in your file
-(BOOL)isDictionaryWord:(NSString*)word {
UITextChecker *checker = [[UITextChecker alloc] init];
NSLocale *currentLocale = [NSLocale currentLocale];
NSString *currentLanguage = [currentLocale objectForKey:NSLocaleLanguageCode];
NSRange searchRange = NSMakeRange(0, [word length]);
NSRange misspelledRange = [checker rangeOfMisspelledWordInString:word range: searchRange
startingAt:0 wrap:NO language: currentLanguage ];
return misspelledRange.location == NSNotFound;
}
You will have to roll your own. Here's a rough (iOS 5 and later):
Drop a view with transparent background on top of the text view.
Find the visible range of text like so:
- (NSRange)visibleRangeOfTextView:(UITextView *)textView {
CGRect bounds = textView.bounds;
UITextPosition *start = [textView characterRangeAtPoint:bounds.origin].start;
UITextPosition *end = [textView characterRangeAtPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))].end;
return NSMakeRange([textView offsetFromPosition:textView.beginningOfDocument toPosition:start],
[textView offsetFromPosition:start toPosition:end]);
}
Search for misspelled words in that range.
Find their on-screen coordinates using UITextView firstRectForRange method.
Highlight any way you want.
Deciding when to do this is left as an exercise for the eager student :)

Weird UITextView behavior

I have a UITextView which i create in the code:
myView = [[UITextView alloc] initWithFrame:CGRectMake(10,5,220,50)];
myView.editable = YES;
myView.font = [UIFont fontWithName:#"Helvetica" size:16];
myView.bounces = NO;
myView.delegate = self;
I set UIView *myView in the header as well..
and also set delegate - UIViewController UITextViewDelegate>
I want to hide a label every time the user writes a text
for that i check if its equal to 0, else its hide.
the problem is in this method -
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if(textView.text.length == 0)
descLabel.hidden = NO;
else
descLabel.hidden = YES;
return YES;
}
the program runs but when i enter the first letter the label still there,
and when i enter the second letter it goes as it should. then i delete those two and its still gone! (reminder: i want the label to be hidden when the length is 0) but when i press on the delete again i can see the label. Pretty weird..
I want to have the behavior of a placeholder in UITextView but this problem annoying
Thanks for your help!
You are checking the textView.text value before the change; you presumably want to check the length after the update would be applied.
e.g.:
NSString *newString = [textView.text stringByReplacingCharactersInRange:range withString:text];