2013-10-30 81 views
2

我想製作一個同步的演出歌詞應用程序和所有歌詞UITextView上顯示。爲了突出顯示當前的歌詞,我添加了NSAttributedStringUITextView背景色。存儲在NSArray中的所有行的所有NSRange不正確的滾動UITextView與NSAttributedString

我的代碼非常簡單,點擊按鈕時將高亮線向下移動(通過設置UITextView的contentOffset)。但是這裏發生了一個奇怪的問題在開始時,UITextView正確滾動,但當UITextViewcontentOffset大於其frame.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 

我所有的代碼是在視圖控制器和StoryBoard有兩個的UIButton和一個UITextView。 我想知道的是「爲什麼UITextView.contentOffset在大於某個尺寸時無法更改」。

回答

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