简体   繁体   中英

How to scroll to specific portion of an attributed string

I have an NSMutableAttributedString that lives inside a UIScrollView. I highlight a portion of the string using the addAttributes:range: function.

When a lot of text is present, I currently have to manually scroll quite a ways to get to the highlighted part. I'd like to come up with a way to have the view automatically scroll to the highlighted portion when the view is loaded - sort of how you can use anchors to link to a specific part of a webpage .

I'm guessing there is a function that, given some kind of numbers will allow me to scroll to a specific part of my page? How might I come up with such numbers to provide to such a function? Using the NSRange component from the attributed string?

Perhaps there is better way to accomplish this?

UIScrollView has the method setContentOffset:animated: which would allow you to scroll to a particular point in your content. To figure out what the appropriate offset is, you would have to determine the width of the portion of your attributed string prior to the highlighted part. The documentation for the methods you use to do this can be found here . You could do this using the size method of NSAttributedString .

It would look something like this:

@interface SomeViewController : UIViewController
@end

@implementation SomeViewController {
    UIScrollView* _scrollView;
}

- (void)scrollToOffset:(NSInteger)offset inAttributedString:(NSAttributedString*)attributedString {
    NSAttributedString* attributedSubstring = [attributedString attributedSubstringFromRange:NSMakeRange(0, offset)];
    CGFloat width = attributedSubstring.size.width;
    [_scrollView setContentOffset:CGPointMake(width, 0.0f) animated:YES];
}
@end

The above code assumes that we're talking about a single line of text and that scrolls horizontally. Alternatively to do this for a fixed width that wraps to an arbitrary height you would need to calculate height with the following code (rather than attributedSubstring.size.height) and then possibly subtract a little to account for wanting to show the last line that of the substring:

    CGFloat height = [attributedSubstring boundingRectWithSize:CGSizeMake(<#fixed width to wrap at#>, HUGE_VALF) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size.height;
    [_scrollView setContentOffset:CGPointMake(0.0f, height) animated:YES];

This is similar to code I use when determining the height of table or collection view cells that have dynamic text that I need to accommodate.

I did not specify it in my original question, but I will address it here. The accepted answer above provides a solution when one wants to scroll horizontally to a specified portion of text. However, in order to scroll vertically a solution similar to that of below is required - other methods may exist but this is what worked for me.

Notice that instead of getting the size component from the attributed sub-string itself, we are getting the size from the view AFTER we've added the sub-string to it. We then insert the full string and force the scroll:

NSAttributedString* att_string = [[NSMutableAttributedString alloc] initWithString:mystring];
NSAttributedString* sub_string = [att_string attributedSubstringFromRange:NSMakeRange(0, highlight_begin_index)];

[the_view setAttributedText:attributedSubstring];

CGFloat jump_height = the_view.contentSize.height;

[the_view setAttributedText:att_string];
[the_view setContentOffset:CGPointMake(the_view.contentOffset.x,jump_height) animated:FALSE];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM