2

我想制作一个同步的显示歌词应用程序,并将所有歌词显示在UITextView. 为了突出当前的歌词,我在 of 中添加了背景NSAttributedString颜色UITextViewNSRange存储在NSArray.

我的代码非常简单,当点击按钮时,将高亮线向下移动(通过 UITextView 的 set contentOffset)。但是这里出现了一个奇怪的问题。一开始,UITextView卷轴是正确的,但当大于它时contentOffset,它是固定的。UITextViewframe.size.height

这是我的代码:

//View controller
#import "ViewController.h"

@interface ViewController () {
    NSUInteger globelIndex;
    NSArray *textRanges;
    NSMutableAttributedString *attributedText;
}

@property (weak, nonatomic) IBOutlet UITextView *lyricView;
@property (strong, nonatomic) NSTimer *mainTimer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSString *rawText = [self readFile];
    globelIndex = 0;
    [self initTextLines:rawText];
    attributedText = [[NSMutableAttributedString alloc] initWithString:rawText
                                                            attributes:@{NSBackgroundColorAttributeName: [UIColor orangeColor]}];

    self.lyricView.attributedText = [attributedText copy];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)manualNextLine:(UIButton *)sender {
    [self updateTextView];
}

- (IBAction)autoNextLineUsingNSTimer:(UIButton *)sender {
    self.mainTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTextView) userInfo:nil repeats:YES];
}

- (void)updateTextView {
    if (self.lyricView.contentOffset.y >= self.lyricView.contentSize.height &&
        self.mainTimer)
    {
        self.mainTimer = nil;
        return;
    }

    NSMutableAttributedString *mat = [attributedText mutableCopy];
    NSValue *value = [textRanges objectAtIndex:globelIndex];
    [mat addAttribute:NSBackgroundColorAttributeName value:[UIColor whiteColor] range:[value rangeValue]];

    self.lyricView.attributedText = [mat copy];

    globelIndex += 1;

    //    self.textView.contentOffset = CGPointMake(self.textView.contentOffset.x, self.textView.contentOffset.y + 24);

    //    [self.textView scrollRangeToVisible:[value rangeValue]];
    CGPoint newOffset = CGPointMake(self.lyricView.contentOffset.x, self.lyricView.contentOffset.y + 20);
    [self.lyricView setContentOffset:newOffset animated:NO];

    NSLog(@"[%@ %@] h: %f b: %f a: %f", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.lyricView.contentSize.height, newOffset.y, self.lyricView.contentOffset.y);
}

#pragma mark - helper

- (void)initTextLines:(NSString *)rawText {
    NSMutableArray *result = [@[] mutableCopy];
    NSArray *t = [rawText componentsSeparatedByString:@"\r\n"];
    __block int index = 0;

    [t enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSString *s = obj;
        NSRange range = NSMakeRange(index, s.length + 2);
        [result addObject:[NSValue valueWithRange:range]];
        index += s.length + 2;
    }];


    textRanges = [result copy];
}

- (NSString *)readFile {
    NSError *error = nil;
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"二人の季節が-ささきのぞみ-想い" withExtension:@"lrc"];
    NSString *content = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:&error];
    if (error) {
        if (DEBUG) NSLog(@"[%@ %@] Error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
        abort();
    }
    return content;
}

@end

我所有的代码都在 ViewController 中,并且StoryBoard有两个 UIButton 和一个 UITextView。我想知道的是“为什么 UITextView.contentOffset 在大于某个大小时不能改变”。

4

1 回答 1

0

也许重写setContentOffset:animated对你有帮助!

这是一些您可以借用的示例代码:
https ://github.com/360/Three20/blob/master/src/Three20UI/Sources/TTTextView.m

#import "Three20UI/TTTextView.h"

// UI
#import "Three20UI/UIViewAdditions.h"

@implementation TTTextView

@synthesize autoresizesToText = _autoresizesToText;
@synthesize overflowed        = _overflowed;

- (void)setContentOffset:(CGPoint)offset animated:(BOOL)animated {
  if (_autoresizesToText) {
    if (!_overflowed) {
      // In autosizing mode, we don't ever allow the text view to scroll past zero
      // unless it has past its maximum number of lines
      [super setContentOffset:CGPointZero animated:animated];

    } else {
      // If there is an overflow, we force the text view to keep the cursor at the bottom of the
      // view.
      [super setContentOffset: CGPointMake(offset.x, self.contentSize.height - self.height)
                     animated: animated];
    }

  } else {
    [super setContentOffset:offset animated:animated];
  }
}


@end
于 2015-08-21T09:17:22.957 回答