套路继续, .txt 小说阅读器功能开发

本文介绍了在开发iOS .txt小说阅读器时遇到的问题及解决方案,包括消除正文与右边界之间的多余空白、实现整行复制功能、灵活选择复制文字以及高亮显示选中行。通过修改富文本属性、使用长按手势和Core Text渲染,提升阅读器的用户体验。
摘要由CSDN通过智能技术生成

1, 解决一个 bug

正文结尾 (最后一行最后一个字)跟右边界, 有多余的空白间隔

Core Text 的渲染流程,就是富文本绘制

从流程上看,

感觉这一页的文字分配少了,给他加点字,就满了

// 拿到一个章节的富文本,计算出每一页的富文本,从哪里开始,哪里结束
// 得到一个范围的数组,就知道了每一页的文字
class func pagingRanges(attrString:NSAttributedString, rect:CGRect) ->[NSRange] {
        var rangeArray = [NSRange]()
        let framesetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
        // 屏幕显示区域
        let path = CGPath(rect: rect, transform: nil)
        var range = CFRangeMake(0, 0)
        var rangeOffset = 0
        repeat{
            let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(rangeOffset, 0), path, nil)
            range = CTFrameGetVisibleStringRange(frame)
            rangeArray.append(NSMakeRange(rangeOffset, range.length))
            rangeOffset += range.length
        }while(rangeOffset < attrString.length)
        return rangeArray
    }

这样做,效果很不好

解决:

修改富文本属性, 怎么换行的


            // 行间距
            paragraphStyle.lineSpacing = lineSpacing
            // 加了这么一句
            paragraphStyle.lineBreakMode = .byCharWrapping
            // 段间距
            paragraphStyle.paragraphSpacing = paragraphSpacing
            
            // 对齐
            paragraphStyle.alignment = .justified

2, 复制一整行

基于 dengzemiao/DZMeBookRead

长按,可复制一整行

长按的时候,要找出这一行,

给这一行涂上颜色,

出来一个可复制的菜单


/// 长按事件
    @objc private func longAction(long:UILongPressGestureRecognizer) {
        
        // 触摸位置
        let point = long.location(in: self)

        // 触摸位置
        switch long.state {
        case .began:
            // 触摸开始 触摸中
            // 发送通知, 处理其他 UI
            // ...
        //      case .changed:
        default:
            // 触摸结束

            // 获得选中区域
            selectRange = CoreText.GetTouchLineRange(point: point, frameRef: frameRef)

            // 获得选中选中范围
            rects = CoreText.GetRangeRects(range: selectRange!, frameRef: frameRef, content: pagingModel.content?.string)

            // 显示光标
            cursor(isShow: true)


                // 显示菜单
            self.showMenu(isShow: true)
            

            // 重绘
            setNeedsDisplay()

            // 发送通知, 处理其他 UI
            // ...
        }
    }

找出这一行

长按手势,可以拿到一个点,

当前阅读界面,有一帧的文字 CTFrame

    
    /// 获得触摸位置那一行文字的Range
    ///
    /// - Parameters:
    ///   - point: 触摸位置
    ///   - frameRef: CTFrame
    /// - Returns: CTLine
    class func GetTouchLineRange(po
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值