BookTextView
效果
说明
1. 支持富文本
2. 支持自定义view
3. 支持阅读百分比
源码
https://github.com/YouXianMing/UI-Component-Collection
//
// BookTextView.h
// InTheQuietNight
//
// Created by YouXianMing on 15/5/18.
// Copyright (c) 2015年 XianMingYou. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ExclusionView.h"
#import "ConfigAttributedString.h"
@interface BookTextView : UIView
// 要显示的文本
@property (nonatomic, strong) NSString *textString;
// 段落样式的设置
@property (nonatomic, strong) NSDictionary *paragraphAttributes;
// 富文本参数数组(ConfigAttributedString对象的数组)
@property (nonatomic, strong) NSArray *attributes;
// 计算出的文本的高度
@property (nonatomic, readonly) CGFloat textHeight;
// 当前文本已读百分比
@property (nonatomic, readonly) CGFloat currentPercent;
// 存储的图文混排的views
@property (nonatomic, strong) NSArray *exclusionViews;
/**
* 构建出组件(设置完所有参数后再做)
*/
- (void)buildWidgetView;
/**
* 移动到指定的位置(此方法只有延时执行才有效果,比如延时执行0.01s)
*
* @param position 文本的高度位置
*/
- (void)moveToTextPosition:(CGFloat)position;
/**
* 移动到指定的百分比(此方法只有延时执行才有效果,比如延时执行0.01s)
*
* @param percent 百分比
*/
- (void)moveToTextPercent:(CGFloat)percent;
@end
//
// BookTextView.m
// InTheQuietNight
//
// Created by YouXianMing on 15/5/18.
// Copyright (c) 2015年 XianMingYou. All rights reserved.
//
#import "BookTextView.h"
typedef enum : NSUInteger {
EBOOK_NONE, // 什么也不做
EBOOK_CALCULATE_HEIGHT, // 计算文本高度
} EBookTextViewStatus;
@interface BookTextView ()<UITextViewDelegate> {
EBookTextViewStatus _bookStatus;
CGFloat _tmpOffsetY;
CGFloat _tmpPercent;
}
@property (nonatomic, strong) UITextView *textView;
@property (nonatomic) CGFloat textHeight;
@property (nonatomic) CGFloat currentPercent;
@end
@implementation BookTextView
- (void)buildWidgetView {
// 获取长宽
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
// 创建文本容器并设置段落样式
NSTextStorage *storage = [[NSTextStorage alloc] initWithString:self.textString
attributes:self.paragraphAttributes];
// 设置富文本
for (int count = 0; count < _attributes.count; count++) {
ConfigAttributedString *oneConfig = _attributes[count];
[storage addAttribute:oneConfig.attribute
value:oneConfig.value
range:oneConfig.range];
}
// 管理器
NSLayoutManager *layoutManager = [NSLayoutManager new];
[storage addLayoutManager:layoutManager];
// 显示的容器
NSTextContainer *textContainer = [NSTextContainer new];
CGSize size = CGSizeMake(width, MAXFLOAT);
textContainer.size = size;
[layoutManager addTextContainer:textContainer];
// 给TextView添加带有内容和布局的容器
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, width, height)
textContainer:textContainer];
self.textView.scrollEnabled = YES;
self.textView.editable = NO;
self.textView.selectable = NO;
self.textView.layer.masksToBounds = YES;
self.textView.showsVerticalScrollIndicator = NO;
self.textView.delegate = self;
// 如果有额外的views
if (self.exclusionViews) {
NSMutableArray *pathArray = [NSMutableArray arrayWithCapacity:_exclusionViews.count];
// 添加view + 添加path
for (int count = 0; count < _exclusionViews.count; count++) {
// 添加view
ExclusionView *tmpView = _exclusionViews[count];
[_textView addSubview:tmpView];
// 添加path
[pathArray addObject:tmpView.createUIBezierPath];
}
textContainer.exclusionPaths = pathArray;
}
// 添加要显示的view
[self addSubview:self.textView];
// 存储文本高度
[self storeBookHeight];
}
- (void)storeBookHeight {
// 先偏移到文本末尾位置
_bookStatus = EBOOK_CALCULATE_HEIGHT;
[UIView setAnimationsEnabled:NO];
[self.textView scrollRangeToVisible:NSMakeRange([self.textView.text length], 0)];
[UIView setAnimationsEnabled:YES];
_bookStatus = EBOOK_NONE;
// 再偏移到文本开头位置
[UIView setAnimationsEnabled:NO];
[self.textView scrollRangeToVisible:NSMakeRange(0, 0)];
[UIView setAnimationsEnabled:YES];
}
- (void)moveToTextPosition:(CGFloat)position {
[self.textView setContentOffset:CGPointMake(0, position) animated:NO];
}
- (void)moveToTextPercent:(CGFloat)percent {
// 计算出百分比
CGFloat position = 0.f;
if (percent >= 0 && percent <= 1) {
position = percent * _textHeight;
} else if (percent < 0) {
position = 0.f;
} else {
position = _textHeight;
}
// 移动到指定的位置
[self.textView setContentOffset:CGPointMake(0, position) animated:NO];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Y轴偏移量
_tmpOffsetY = scrollView.contentOffset.y;
if (_bookStatus == EBOOK_NONE) {
_tmpPercent = _tmpOffsetY / _textHeight;
if (_tmpPercent >= 0 && _tmpPercent <= 1) {
_currentPercent = _tmpPercent;
} else if (_tmpPercent < 0) {
_currentPercent = 0.f;
} else {
_currentPercent = 1.f;
}
NSLog(@"%f", _currentPercent);
} else if (_bookStatus == EBOOK_CALCULATE_HEIGHT) {
self.textHeight = scrollView.contentOffset.y;
}
}
@end