Обоснуйте последнюю строку UITextView - PullRequest
0 голосов
/ 19 февраля 2020

Я работаю над проектом, похожим на книгу. Где есть список абзацев на нескольких страницах, которые вы можете прокрутить. Я создаю отдельный UITextView для каждой отдельной страницы и устанавливаю его как оправданный для создания подобного книжного опыта. К сожалению, последняя строка UITextView неоправданна (потому что я использую новый UITextView для каждой отдельной страницы). Так что на самом деле UITextView ведет себя правильно. Но так как мой абзац продолжается на следующей странице, я бы хотел, чтобы это было express, оправдывая последнюю строку. Я использую UITextView, чтобы предоставить пользователю возможность выделять и копировать части текста.

Вот как это выглядит сейчас.

Это то, что ожидается.

1 Ответ

0 голосов
/ 20 февраля 2020

Я добавил категорию в UITextView, чтобы выполнить вычисления, которые нам нужны для последней строки. Это могут быть либо отдельные файлы .h / .m, либо размещенные в верхней части файла .m там, где вам нужно их использовать. Обратите внимание, что это работает со свойствами attribute.Text и textContainer. Свойство attributetedText устанавливается (начиная с iOS7), даже если вы устанавливаете только текстовое свойство в UITextView. Свойство textContainer определяет размер области, в которой UITextView будет отображать свой текст, но вам может понадобиться немного отличаться, если вы используете ограничения для разметки UITextView.

@interface UITextView (LastLineRange)

- (NSRange) lastLineRange;

@end

@implementation UITextView (LastLineRange)

- (NSRange)lastLineRange
{
    // calculate the bounds for the text rendered in the UITextView
    CGSize textSize = [self.attributedText boundingRectWithSize:self.textContainer.size
                                                        options:NSStringDrawingUsesLineFragmentOrigin
                                                        context:nil].size;

    // we care about the last line, so get the start and end points along the bottom of the bounds
    UITextPosition* start = [self characterRangeAtPoint:CGPointMake(0, textSize.height)].start;
    UITextPosition* end = [self characterRangeAtPoint:CGPointMake(textSize.width, textSize.height)].end;

    // turn the text positions into indices we can make a range with
    NSInteger startLoc = [self offsetFromPosition:self.beginningOfDocument
                                       toPosition:start];

    // this should not be 'endOfDocument', but the end that we calculated above,
    // since this represents the end of the visible text
    NSInteger endLoc = [self offsetFromPosition:start
                                     toPosition:end];

    return NSMakeRange(startLoc, endLoc);
}

@end

Вот как Я использовал категорию, чтобы получить последнюю строку и применить к ней стиль выровненного по правому краю абзаца. Я пытался добавить комментарии, чтобы было понятно, что происходит. Я просто набросал фактический UITextView, так что он не так хорош, как ваш пример, но должен дать вам идею.

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIFont* font = [UIFont systemFontOfSize:20.0];

    // used for the main, left-aligned text
    NSMutableParagraphStyle* pStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    pStyle.lineBreakMode = NSLineBreakByWordWrapping;
    pStyle.alignment = NSTextAlignmentLeft;

    // used for the last line, which will be right-aligned
    NSMutableParagraphStyle* lastStyle = [pStyle mutableCopy];
    lastStyle.alignment = NSTextAlignmentRight;

    CGRect pageFrame = CGRectMake(self.view.frame.size.width / 4.0,
                                  50.0,
                                  self.view.frame.size.width / 2.0,
                                  self.view.frame.size.height / 2.0);

    UITextView* page = [[UITextView alloc] initWithFrame:pageFrame
                                            textContainer:nil];

    page.scrollEnabled = false;
    page.editable = false;

    // attributes for main text
    NSDictionary* lAlignedAttrs = @{
                                    NSFontAttributeName : font,
                                    NSParagraphStyleAttributeName : pStyle
                                   };

    // attributes for the last line of text
    NSDictionary* rAlignedAttrs = @{
                                    NSFontAttributeName : font,
                                    NSParagraphStyleAttributeName : lastStyle,
                                    // only added this to highlight the last line changes
                                    NSForegroundColorAttributeName : [UIColor redColor]
                                   };

    // needs to be mutable, so we can set attributes at certain ranges
    NSMutableAttributedString* text1 = [[NSMutableAttributedString alloc] initWithString:text
                                                                    attributes:lAlignedAttrs];

    // now set the attributed text as content for the UITextView, since
    // we will use the category for finding the last line
    page.attributedText = text1;

    // here, we ensure that the last line will be considered a new paragraph
    // so the paragraph style changes we make will take effect
    NSInteger insertionIndex = page.lastLineRange.location;
    if ( [text1.string characterAtIndex:insertionIndex] != '\n' )
    {
        [text1 insertAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]
                              atIndex:insertionIndex];
    }

    // apply right-aligned paragraph style over the range of the last line
    [text1 setAttributes:rAlignedAttrs
                   range:page.lastLineRange];

    // we have altered the attributed text, so need to set the new text
    // as the content for the UITextView
    page.attributedText = text1;

    [self.view addSubview:page];
}


@end

Вот что я достиг с этим: Right-Aligned Last Line Text

...