Truncate text in TTStyledTextLabel - iphone

I am using a TTStyledTextLabel in my project to parse the hyperlinks, it all works fine. The only problem I am facing is to truncate a long text - show ellipses if the text does not fit in the bounds of TTStyledTextLabel.
In other terms, I need the same behavior as a UILabel which adds ellipses to indicate that some text is clipped. I have searched in TTStyledTextLabel and TTStyledText classes, there is no provision to achieve this. The following is the code which I have used in my UITableViewCell subclass to set the frame of TTStyledTextLabel appropriately:
-(void) layoutSubviews
{
[super layoutSubviews];
.
.
.
CGSize maxSize = CGSizeMake(self.contentView.frame.size.width -TEXT_OFFSET_WIDTH, TT_TEXT_MAX_HEIGHT);
[[[self textLabelTTStyled] text] setWidth:maxSize.width];
[[self textLabelTTStyled] sizeToFit];
double heigthForTTLabel = [[[self textLabelTTStyled] text] height];
if (heigthForTTLabel > maxSize.height)
heigthForTTLabel = maxSize.height; // Do not exceed the maximum height for the TTStyledTextLabel.
**// The Text was supposed to clip here when maximum height is set!**
CGSize mTempSize = CGSizeMake([[[self textLabelTTStyled] text] width], heigthForTTLabel);
CGRect frame = CGRectMake(TEXT_OFFSET_X,TEXT_OFFSET_Y,mTempSize.width, mTempSize.height);
self.textLabelTTStyled.frame = frame;
.
.
.
}
And in the tableView:cellForRowAtIndexPath: I am setting text like this to my TTStyledTextLabel:
TTStyledText *styledStatusMessage = [TTStyledText textFromXHTML:#"This is a really long text, how long can this go on? This is a really long text, how long can this go on? This is a really long text, how long can this go on? This is a really long text, how long can this go on? This is a really long text, how long can this go on? This is a really long text, how long can this go on?"
lineBreaks:YES URLs:YES];
if (nil == styledStatusMessage) {
styledStatusMessage = [TTStyledText textWithURLs:[statusMessage title] lineBreaks:YES];
[[cell textLabelTTStyled] setText:styledStatusMessage];
}
The excessive text is simply being discarded, the ellipses are not added by default to indicate that text is clipped. Any solutions to this problem?
Thanks,
Raj

I believe you are using a private api Three20 which is having a chance oof rejection from appstore.Just check once before you upload.
Genrally you can set any set any custom button with setting title on it
[button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 10.0, 0.0, 0.0)]; - This line can be used for settting title edges. Hope it helps.

Related

iOS 7 UITextView height resize quirk

Using information I've gathered from multiple answers I found here on stackoverflow, I've been able to correctly size a UITextView's height using:
[bookQuoteTxtView sizeToFit];
[bookQuoteTxtView layoutIfNeeded];
I'm doing this because the UITextView will obviously contain different amounts of text as a result of what the user may have selected on a previous screen.
However, I'm still running into one strange problem.
It seems that when the text that gets passed into the UITextView contains a line-break, it throws the whole height thing off.
Here's the text without any line-breaks:
And here's the same text with a couple of line-breaks thrown in the middle:
As you can see (with the help of the orange & yellow background colors I added to the UITextView & ScrollView that contains it), the UITextView's height didn't resize appropriately and now the text gets cut off - all because of those linebreaks.
The code I'm using to do all this dynamic height-changing on the UITextView is:
// BookQuote TextView:
bookQuoteTxtView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 310, 80)];
bookQuoteTxtView.backgroundColor = [UIColor orangeColor];
bookQuoteTxtView.font = [UIFont fontWithName:#"Arial" size:15];
bookQuoteTxtView.text = [NSString stringWithFormat:#"%#", bookObject.bookQuote];
[bookQuoteTxtView sizeToFit];
[bookQuoteTxtView layoutIfNeeded];
bookQuoteTxtView.editable = NO;
[scroller addSubview:bookQuoteTxtView];
// Now get the HEIGHT of the Book-Quote TextView:
CGRect textViewFrame = bookQuoteTxtView.frame;
CGFloat textViewFrameHeight = bookQuoteTxtView.contentSize.height;
textViewFrame.size.height = textViewFrameHeight;
bookQuoteTxtView.frame = textViewFrame;
So again, this works almost flawlessly for just about every string that gets passed into my UITextView box. Thus, different strings of different lengths all work, the UITextView's height adjusts automatically and everything's cool. Its just the line-breaks that throw everything off.
HAVING SAID THAT...
Its seems that line-breaks generated using "\n" in the string DO work, but line breaks that are embedded/encoded in a string that's coming in and being read from an Sqlite3 database - do NOT.
So you gotta wonder if that's where the problem lies.
Here's the code I use to read my date from the Database:
// Book Quote:
char *bookQuoteChar = (char *)sqlite3_column_text(statement, 4);
NSString *bookQuoteString;
if (bookQuoteChar == NULL) {
bookQuoteString = #"N/A";
}
else {
bookQuoteString = [[NSString alloc] initWithUTF8String:bookQuoteChar];
}
I'm thinking more and more that its the database that's causing the problem, but I'm presenting the entire picture here in its totality to make sure I'm still doing the height-readjustment stuff correctly.
Please let me know if something's jumping out at you or if there are any suggestions for fixes.
I can't really suggest much besides using a technique to set the contentSize of the UITextView.
textView.text = #"text from DB";
CGRect rect = textView.frame;
rect.size.height = textView.contentSize.height;
textView.frame = rect;
and then use any techniques that may be needed to additionally update the frame. Hope you solve the problem!

Initializing UITextView based on the available text font size and font name

This is what i have tried,
UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = #"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;//Here i am adjusting the textview
[self.view addSubview:_textView];
Basically after fitting the text into textview,scrolling is enable,but i cannot view the content inside the textview without scrolling the textview.I do want to initialize the UITextView frame size based on the text size,font name etc.
Any solution is appreciated.Thanks.
NSString *str = #"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
UIFont * myFont = [UIFont fontWithName:#"your font Name"size:12];//specify your font details here
//then calculate the required height for the above text.
CGSize textviewSize = [str sizeWithFont:myFont constrainedToSize:CGSizeMake(300, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
//initialize your textview based on the height you got from the above
UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, textviewSize.width, textviewSize.height)];
_textView.text = str;
[self.view addSubview:_textView];
And also you want to disable the scrolling in textview then refer this.
As William Jockusch states in his answer here:
You can disable almost all scrolling by putting the following method
into your UITextView subclass:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
// do nothing
}
The reason I say "almost" all scrolling is that even with the above,
it still accepts user scrolls. Though you could disable those by
setting self.scrollEnabled to NO.
If you want to only disable some scrolls, then make an ivar, lets call
it acceptScrolls, to determine whether you want to allow scrolling or
not. Then your scrollRectToVisible method can look like this:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
if (self.acceptScrolls)
[super scrollRectToVisible: rect animated: animated];
}

How can I get the UITextView to scroll only when it's full of text

I have this UITextView that works great except, I can't get the text inside the UITextView to start scrolling only after the UITextView's size in nearly full, the UITextView is 4 lines tall, but as soon as I reach the 2nd line the 1st line is pushed up, I don't want the view to begin scrolling until I've reached the 5 line. scrollingEnabled = NO keeps it from scrolling at all, so that didn't work.
UITextView *barf_ = [[UITextView alloc] initWithFrame:CGRectMake(20.0, 310.0, 155, 50)];
barf_.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
//[barf_ scrollRangeToVisible:NSMakeRange([barf_.text length], 0)];
barf_.layer.cornerRadius = 3.0f;
barf_.layer.borderWidth = 0.5f;
barf_.font = [UIFont fontWithName:#"Helvetica" size:13];
I found the answer, as others with similar problems have mention, with a small textView, it automatically adds 32 padding to the bottom.
A simple fix is to add YourTextView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); inside shouldChangeTextInRange method, that fixed my problem!
Setting the contentInset may help the text to appear more correctly within the UITextView. However, it won't help solve the issue whereby the UITextView has scrolling enabled despite not having more text to view.
Similarly, methods such as sizeWithFont have limitations. As explained in Mike Weller's excellent blog series iOS Development: You're Doing It Wrong, NSString isn't a good object to ask regarding how large a UIView should be. Many UIView subclasses such as UILabel, UIButton, etc. have insets and other considerations that must be accounted for during sizing. UITextLabel is no exception.
Mike Weller's particular entry on this subject is:
You're Doing It Wrong #2: Sizing labels with -[NSString sizeWithFont:...]
iOS 7 promises us more sophisticated text handling in UITextView, with properties such as textContainerInset. But what to do in the meantime?
Well, first we know that UITextView is a subclass of UIScrollView. Therefore, the golden rule that if the contentSize is larger than the view's bounds property, the scroll view will scroll so we can see more content.
Checking out contentSize agains the bounds won't work either because we know that UIScrollView is already calculating whether it should scroll or not based on the text, and it's giving us the wrong answer.
This is where arbitrary adjustment values come to the rescue! For me this value was 17.f. For you - depending on your fonts - it maybe different. We then take control and decide whether we should allow the scroll view to scroll:
static const CGFloat kArbritaryHeight = 17.f;
CGFloat adjustedContentHeight = myTextView.contentSize.height - kArbritaryHeight;
CGFloat boundsHeight = CGRectGetHeight(myTextView.bounds);
BOOL tooMuchContent = adjustedContentHeight > boundsHeight;
if (tooMuchContent)
{
myTextView.scrollEnabled = YES;
}
else
{
myTextView.scrollEnabled = NO;
}
When your UITextView is loaded set scrollEnabled to NO. Then set the text view's delegate to self or some other object and implement the UITextViewDelegate method
- (void)textViewDidChange:(UITextView *)textView
This method will get called anytime the user makes a change to the text inside the view. Inside this method you need to figure out how big your text is and if it goes beyond the bounds of the text view. If so you enable scrolling. Use this method:
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
This is a UIKit category method on NSString. It returns a CGSize that will tell you the height of whatever text string you call it on. In your case it would be something like
CGSize textSize = [textView.text sizeWithFont:textView.font
constrainedToSize:CGSizeMake(textView.frame.size.width, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
if (textSize.height > textView.frame.size.height) {
textView.scrollEnabled = YES;
} else {
textView.scrollEnabled = NO;
}
You might use the sizeWithFont:constrainedToSize:lineBreakMode: method to check whether your string will actually render larger than your text view and see if you need to enable scrolling. You will have to call it any time the text in your scrollview is set, however.
ex:
CGSize barfStringSize = [barfString sizeWithFont:[barf_ font]
constrainedToSize:CGSizeMake(barf_.bounds.size.width, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap]
[barf_ setScrollEnabled:barfStringSize.height > barf_.bounds.size.height]

Finding the number of lines in UITextView

I'm using UIScrollView in which I have placed a UIImageView and a UITextView. I make the UIScrollView to scroll both the images and text and it works fine, but my UITextView contains dynamic text (i.e number of lines is different for each time). So I can't find the way to assign contentSize of UITextView. Is there any way to do this?
This and this might help you.
You can put a condition that if width of the new CGSize is greater than textview width then number of lines = 2 else 1.
calculate the text width and define your text view width using below code
+(float) calculateHeightOfTextFromWidth:(NSString *) text: (UIFont *)withFont: (float)width
:(UILineBreakMode)lineBreakMode
{
[text retain];
[withFont retain];
CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(215, 1000) lineBreakMode:lineBreakMode];
[text release];
[withFont release];
return suggestedSize.height;
}
and use when you want to display dynamic text as
float titleHeight;
titleHeight = [Your view controllre ViewController calculateHeightOfTextFromWidth:[NSString stringWithFormat:#"%#",[dict objectForKey:#"title"]] :[UIFont systemFontOfSize:14]:300 :UILineBreakModeTailTruncation];
give this titleHeight to your textview or do calculation dividation using titleheight ,you can get the number of lines
If you get problem then reply

How to split text into separate UITextView pages?

A subquestion is:
How do I determine what the built-in internal margins of a UITextview are?
I have a long master string of text that I am trying to split into separate UITextView pages that I can then scroll from page to page inside a UIScrollView. I use the following method to determine what the height of a string in a UITextView is and whether the string is over the height limit:
-(NSNumber *)getHeightByWidth: (NSString *) myString
mySize: (UIFont *) mySize
myWidth: (NSNumber *) myWidth
{
int intMyWidth = [myWidth intValue];
CGSize boundingSize = CGSizeMake(intMyWidth, CGFLOAT_MAX);
CGSize requiredSize = [myString sizeWithFont:mySize constrainedToSize:boundingSize lineBreakMode:UILineBreakModeWordWrap];
NSNumber *retNumber = [[NSNumber alloc] initWithFloat:requiredSize.height];
return retNumber;
[retNumber release];
}
I call the getHeightByWidth method using the following cellFont as the input for mySize:
UIFont *cellFont = [UIFont fontWithName:#"Arial" size:14.0];
The UITextView is 320 pixels wide, but I notice that the text doesn't go from the left edge to the right edge as there are internal margins which look to be around 10 pixels on each side. So when I call getHeightByWidth I set myWidth = (320 - 10 - 10); But after building strings to fit within the UITextView, there are usually gaps on the last row that could be filled with the next words in the master string.
Can anyone tell me why these gaps on the last row of the text occur using this process for UITextView?
The built-in margins are represented by the property contentInset.
Also you can configure the margins yourself.
If you have your text view in IB, look for Content insets. The values must be 0, but it still displays some margin. Trying setting them to negative values such as -4 or -8.
In the code, do something like-
myTextView.contentInset = UIEdgeInsetsMake(-4,-8,0,0);
You have to set these values according to what you find suitable.