iOS 8 UITextView Fixed text alignment - ios

I have a UITextView in my View Controller, I've overridden the class and in awakeFromNib method I did
if (([NSLocale characterDirectionForLanguage:[[NSLocale preferredLanguages] objectAtIndex:0]] == NSLocaleLanguageDirectionRightToLeft)) {
//Arabic
}
else {
//English
}
For Arabic I did [self setTextAlignment:NSTextAlignmentCenter]; also tried
[self setBaseWritingDirection:UITextWritingDirectionLeftToRight forRange:[self textRangeFromPosition:[self beginningOfDocument] toPosition:[self endOfDocument]]];
also tried
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentLeft;
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:self.text];
[string addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, string.length)];
self.attributedText = string;
by following multiple SO Questions, but no success at all :( My TextView is always right aligned when device language is Arabic. I want it left aligned because I want to show English text.

I was setting the property in awakeFromNib method and that was the issue. I set the textAlignment in my view controller class and it worked fine for me. If anybody can shed some light on this behavior please do.

Related

UILabel attributed text can't have multiple lines if you change baseline offset attribute

I want to change brackets's baseline offset in a words, like "[推]blablabla".
NSRange range = [text rangeOfString:#"[推]"];
if (range.location == 0) {
[text addAttribute:NSBaselineOffsetAttributeName value:#(0.5) range:NSMakeRange(0, 1)];
[text addAttribute:NSBaselineOffsetAttributeName value:#(0.5) range:NSMakeRange(range.length-1, 1)];
}
but the second line of the label disappears and gets truncated. Anyone have an idea?
Please use lineBreakMode and numberOfLines
Also to call sizeToFit, like this:
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
[label sizeToFit];
The height will be automatically computed.
Thanks
I've did some quick test, and it seems that if you add a whitespace at the first of your string, it will work as expected
// make sure your text looks like #" [推]your content"
if (range.location == 1) {
[text addAttribute:NSBaselineOffsetAttributeName value:#(0.5) range:NSMakeRange(1, 1)];
[text addAttribute:NSBaselineOffsetAttributeName value:#(0.5) range:NSMakeRange(range.length, 1)];
}
If you using storyboard see the below image, select the Label, then see the Lines is set 0 and Line Breaks set Word Wrap thats solve.
or if you use code,
Objective C:
LabelName.lineBreakMode = UILineBreakModeWordWrap;
LabelName.numberOfLines = 0;
Swift:
LabelName.lineBreakMode = .ByWordWrapping
LabelName.numberOfLines = 0
hope its helpful
Did you try using NSMutableParagraphStyle to set lineBreakMode as attribute?
NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setLineBreakMode:NSLineBreakByTruncatingTail];
[attributedText addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:NSMakeRange(0, [attributedText length])];
like proposed here: UILabel attributedText with multiple line break modes

Setting attributedText of UILabel causing issue with Lengthier content

In my project I want to add an attributed text in UILabel placed on the xib.
It's working perfectly, but if large text appears it shows some issues.
My current implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
_demoLabel.numberOfLines = 0;
_demoLabel.lineBreakMode = NSLineBreakByWordWrapping;
_demoLabel.attributedText = [self demoNameWithFontSize:21 andColor:[UIColor redColor]];
}
- (NSMutableAttributedString *)demoNameWithFontSize:(CGFloat)fontSize andColor:(UIColor *)color
{
NSMutableAttributedString *attributedText = nil;
NSString *demoName = #"Blah blah blah";
UIFont *demoFont = [UIFont fontWithName:#"Zapfino" size:fontSize];
attributedText = [[NSMutableAttributedString alloc] initWithString:demoName];
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByWordWrapping;
[attributedText addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, [demoName length])];
[attributedText addAttribute:NSFontAttributeName value:demoFont range:NSMakeRange(0, [demoName length])];
[attributedText addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [demoName length])];
return attributedText;
}
Output:
Issue:
It is not displaying the whole text, even if I applied the NSMutableParagraphStyle.
How can I solve this ?
Alternative I found:
If I change
UIFont *demoFont = [UIFont fontWithName:#"Zapfino" size:fontSize];
to
UIFont *demoFont = [UIFont systemFontOfSize:fontSize];
It'll work and gives output like:
But the issue is I need to use custom font, can't use default font. Also cannot change the font size.
I checked UILabel class reference and googled, but couldn't find a solution. Please help me.
Is there anyway to span this text into multiple lines ?
You need to resize the UILabel to fit the text.
You can calculate the size with the boundingRectWithSize:options:context: NSAttributedString class method, which takes an attributed string and calculates the size within a set rect based on all the attributes of the string.

NSMutableAttributedString UILabel is not retaining its attributes when selected

I am having issues with retaining an attributed NSMutableString. I have a UITableView who's each UITableViewCell has an attributed text. Setting the attributed text is no problem, but upon selection, the UITableViewCell's attributes is lost. This is my code in cellForRowAtIndexPath that sets the attribute:
NSMutableAttributedString *changesStyleString_h = [[NSMutableAttributedString alloc] initWithString:#"Attributes change!" attributes:#{NSFontAttributeName: [UIFont boldSystemFontOfSize:20], NSForegroundColorAttributeName:[UIColor yellowColor]}];
[changesStyleString_h addAttributes:#{ NSUnderlineStyleAttributeName:#(1)} range:NSMakeRange(11, 6)];
cell.mainLabel.attributedText = changesStyleString
might i point out that mainLabel is also a UILabel, no customization there. Any help in the right direction would be greatly appreciated!
I found that I needed to set attributes on the ENTIRE string, or it would do funky things.
NSString* string = #"1 - some string"
NSMutableAttributedString* string = [[NSMutableAttributedString alloc] initWithString:string];
[string setAttributes:#{NSForegroundColorAttributeName: accent, NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-Bold" size:13.f]} range:NSMakeRange(0, 1)];
This would cause weird behavior when highlighting the cell.
However, when I did this:
[string setAttributes:#{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(1, [labelTwo length] - 1)];
Everything seemed to work as expected.
Hope that helps!

What is the equivalent of Android's "Spannable" in Objective-C

Im on an iOS app that should able to highlight text, and make it clickable too.
I read about NSAttributedString in iOS but it still more complicated than Spannable in android.
Is there any other Objective c way to do that, if not; what should i do using NSAttributedString to highlight a paragraph word by word, and how to make my text clickable.
Update:
What exactly i want that each word should be clickable and can be
highlighted as a single word in one paragraph.
I found a perfect solution using UITextView, it will make every word in within the UITextView clickable.
Firstly, Create an UITextView and add an UITapGestureRecognizer to it as follows:
CGRect textViewFrame = CGRectMake(0, 40, 100, 100);
textView = [[UITextView alloc]initWithFrame: textViewFrame];
textView.textAlignment = NSTextAlignmentCenter;
textView.backgroundColor = [UIColor clearColor];
textView.editable = NO;
textView.selectable = NO;
[self.view addSubView:textView];
// i used to `NSMutableAttributedString` highlight the text
string = [[NSMutableAttributedString alloc]initWithString:#"Any text to detect A B $ & - +"];
[string addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:40.0]
range:NSMakeRange(0, [string length])];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init] ;
[paragraphStyle setAlignment:NSTextAlignmentCenter];
[string addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [string length])];
[textView setAttributedText:string];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecognized:)];
//modify this number to recognizer number of tap
[singleTap setNumberOfTapsRequired:1];
[textView addGestureRecognizer:singleTap];
Then add the UITapGestureRecognizer #selector:
- (void)tapRecognized:(UITapGestureRecognizer *)recognizer{
if(recognizer.state == UIGestureRecognizerStateRecognized)
{
CGPoint point = [recognizer locationInView:recognizer.view];
NSString * detectedText = [self getWordAtPosition:point inTextView: textView];
if (![detectedText isEqualToString:#""]) {
NSLog(#"detectedText == %#", detectedText);
} }
}
All this magic is related to this method, witch can detect any touch on the UITextView and get the tapped word:
-(NSString*)getWordAtPosition:(CGPoint)pos inTextView:(UITextView*)_tv
{
//eliminate scroll offset
pos.y += _tv.contentOffset.y;
//get location in text from textposition at point
UITextPosition *tapPos = [_tv closestPositionToPoint:pos];
//fetch the word at this position (or nil, if not available)
UITextRange * wr = [_tv.tokenizer rangeEnclosingPosition:tapPos withGranularity:UITextGranularityWord inDirection:UITextLayoutDirectionRight];
return [_tv textInRange:wr];
}
And for highlighting the text:
-(void)setTextHighlited :(NSString *)txt{
for (NSString *word in [textView.attributedText componentsSeparatedByString:#" "]) {
if ([word hasPrefix:txt]) {
NSRange range=[self.textLabel.text rangeOfString:word];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:range];
}}
[textView setAttributedText:string];
}
And thats it, hope this helps others.
Unfortunately the behavior that you're looking for isn't as simple in objective-c as Spannable.
However, it can be accomplished fairly easily:
Create a UILabel or UITextView.
Highlight some of the words using NSMutableAttributedString and NSRange (see below).
Apply the attributed string to the attributedText property.
Create UIButtons with clear backgrounds and no label and position over the top of the clickable words.
Add a target to each button and create a selector method.
Here's some example code for the attributed string to get you started:
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString: [NSString stringWithFormat:#"Text containing a bold word and another"];
[string addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"HelveticaNeue-Bold" size:14] range:NSMakeRange(18,4)];
[string addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"HelveticaNeue-Bold" size:14] range:NSMakeRange(32, 7)];
label.attributedText = string;

Underlining a certain portion of a UILabel

I need to underline a certain portion of a UILabel as the title suggests. For example: Please click ESPNSoccernet to read the latest Football News. I would like to underline the word ESPNSoccernet. This is because I want it to be clickable and it need to link to the website.
Need some guidance on doing this. If there is another way, do tell me...
for ios 6, you can use AttributedStrings
NSMutableAttributedString *yourString = [[NSMutableAttributedString alloc] initWithString:#"Please click ESPNSoccernet to read the latest Football News."];
[yourString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:(NSRange){0,25}];
label.attributedText = [yourString copy];
you can also use a 3rd party UILable library TTTAttributedLabel.
In Xcode:
Select the label and choose identity inspector.
In text choose Attributed instead of plain.
Now Select the portion of text you want to underline.
Select font and choose underline in fonts style.
There you go.
Swift 2.0:
1) Make a nsmutablestring with underline attribute and add to sampleLabel's text.
2) Add a tap gesture to sampleLabel and associate a method for further action.
override func viewDidLoad() {
super.viewDidLoad()
let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapResponse:")
tapGesture.numberOfTapsRequired = 1
sampleLabel.userInteractionEnabled = true
sampleLabel.addGestureRecognizer(tapGesture)
}
func tapResponse(recognizer: UITapGestureRecognizer) {
print("tap")
}
UILabel is only capable of displaying plain text strings (in iOS 6 it can now also display NSAttributedStrings, but this will not work in older iOS versions, so it is best not to rely on this), so you will not be able to do this with a label.
You can look at TTTAttributedLabel for displaying attributed text (so you can add underlines and other formatting), but you will not be able to add hyperlinks with this class.
The options you have for a clickable segment of the string are basically:
Use a plain UILabel and overlay a UIButton over the part that you want to be clickable, or
Use TTTAttributedLabel to achieve the underline effect, and a UITapGestureRecognizer to detect and handle taps (note that this will capture taps on the entire label, not just the underlined part).
For iOS 6:
UILabel *label = [[UILabel alloc] init];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"Tap here to read the latest Football News."];
[string addAttribute:NSUnderlineStyleAttributeName value:#(1) range:NSMakeRange(4, 4)];
label.attributedText = [string copy];
For earlier iOS versions as well as iOS 6:
TTTAttributedLabel *label = [[TTTAttributedLabel alloc] init];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"Tap here to read the latest Football News."];
[string addAttribute:NSUnderlineStyleAttributeName value:#(1) range:NSMakeRange(4, 4)];
label.text = [string copy];
Then add a gesture recogniser and implement handleTap::
UITapGestureRecognizer *recogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[label addGestureRecognizer:recogniser];
- (void)handleTap:(UITapGestureRecognizer *)recogniser {
// Handle the tap here
}
Well, i have done the same thing like this:
Make a custom button with text: ESPNSoccernet, and background clearColor
Add a label as a subview with height 1 and some background color to this button, such that "ESPNSoccernet" looks underlined.
Put the remaining text in a label adjacent to this button, so that it looks like a whole text.
Hope it helps!
Note: if you r doing only >iOS 6.0, you might wanna check the other answers.
If this app for ios 6 or later version in that case you can use NSMutableAttributedString
NSMutableAttributedString *labelText = [[NSMutableAttributedString alloc] initWithString:#"Hello this is demmy label for testing"];
[labelText addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:1]
range:(NSRange){10,10}];
label.attributedText = labelText;
for less version you can use like this..
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 116, 171, 20)];
label.text = #"Hello this is demmy label for testing";
label.textColor = [UIColor whiteColor];
label.font = [UIFont systemFontOfSize:16];
[self.view addSubview:label];
//underline code
CGSize expectedLabelSize = [[m_BCListArray objectAtIndex:tagcount] sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:UILineBreakModeWordWrap];
UIView *viewUnderline=[[UIView alloc] init];
viewUnderline.frame=CGRectMake((label.frame.size.width - expectedLabelSize.width)/2, expectedLabelSize.height + (label.frame.size.height - expectedLabelSize.height)/2, expectedLabelSize.width, 1);
viewUnderline.backgroundColor=[UIColor whiteColor];
[self.view addSubview:viewUnderline];
The following code snippet produces desired result :
NSDictionary *dictAttribute = #{NSForegroundColorAttributeName:[UIColor redColor],NSUnderlineStyleAttributeName:#1};
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:#"Please click ESPNSoccernet to read the latest Football News." attributes:dictAttribute];
lblText.attributedText = attrString;

Resources