zoukankan      html  css  js  c++  java
  • [控件] BookTextView

    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

  • 相关阅读:
    Windows 服务多语言化时读取配置文件失败的问题。
    从开始界面卸载Windows服务时,不小心点击了 取消,此后再次卸载会卸载不掉
    从数据库导出数据时,有的字段是时间,不同的时间向在窗口中去掉时用正则表达式匹配找到不同的时间
    C#使用ManagementObjectSearcher来获取系统信息时会有out of memory的异常
    C# TreeView设置SelectedNode设置无效的问题
    C#判断ListBox是否显示了水平滚动条/横向滚动条
    Jmeter运行不显示cmd对话框
    监控Linux系统所选的服务所占进程内存占用
    Linux的date用法
    shell的循环嵌套语法
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4512205.html
Copyright © 2011-2022 走看看