SubviewAttachingTextView
SubviewAttachingTextView
是 UITextView
的子类,它允许将子视图嵌入到富文本中作为文本附件。此库还提供了一个名为 SubviewAttachingTextViewBehavior
的类,允许在现有的 UITextView
子类中组合附件行为。
要查看 SubviewAttachingTextView
的实际应用,克隆或下载此仓库并检查 SubviewAttachingTextView.xcworkspace
内的 Example.playground
。
工作原理
SubviewAttachingTextView
基于 UITextView
中可用的 NSTextAttachment
和 Text Kit API 构建而成。一个自定义的 NSTextAttachment
子类允许保持对嵌入视图的引用,并且文本视图的 NSLayoutManager
和 NSTextContainer
允许在文本内部布局时查询附件的边界,考虑到所有段落样式属性。通过 NSLayoutManager
和 NSTextStorage
的代理回调可以实现自动布局和附件更新。
要求
- Xcode 11.0+ (使用 Swift 5.0 编写)。
- 为了与 Swift 4.2 兼容,请使用版本 1.4.0。
- 为了与 Swift 4.0 兼容,请使用版本 1.3.0。
- 为了与 Swift 3.x 兼容,请使用版本 1.2.2。
- iOS 8.0+
- 兼容 Objective-C。
安装
Carthage
-
将以下行添加到您的
Cartfile
github "vlas-voloshin/SubviewAttachingTextView"
-
按照Carthage 文档中的说明来构建并将库集成到您的应用程序中。
CocoaPods
-
将以下行添加到您的
Podfile
pod 'SubviewAttachingTextView'
-
执行
pod install
。
手动
- 下载并复制存储库源文件到您的项目,或者将其作为子模块添加到您的 git 仓库。
- 将
SubviewAttachingTextView.xcodeproj
拖放到 Xcode 中的项目或工作区。 - 在项目设置中的“通用”标签下 →
您的目标
,您可能会在“嵌入的二进制文件”中看到 Xcode 添加了一个缺失的框架项。现在先删除它。 - 仍然在“通用”标签下,将
SubviewAttachingTextView.framework
添加到“嵌入的二进制文件”。这应该也会将其添加到“链接的框架和库”中。
使用方法
有两种方法可以将子视图附加行为集成到您的文本视图中;选择适合您需求的一种:
UITextView
的替换项
作为只需将你使用的UITextView
的类更改为SubviewAttachingTextView
(在Swift代码中)或VVSubviewAttachingTextView
(在Objective-C代码和Interface Builder中)。
在自定义子类中
你可以通过遵循SubviewAttachingTextView
的实现,轻松地将SubviewAttachingTextViewBehavior
类集成到你的自定义UITextView
子类中。
- 在
init(frame:, textContainer:)
和init?(coder:)
初始化方法中,创建一个SubviewAttachingTextViewBehavior
对象(Objective-C中的VVSubviewAttachingTextViewBehavior
),并将其存储在文本视图实例中。 - 将你的文本视图分配给行为对象的
textView
属性。这是一个弱引用属性,因此这不会创建一个保留周期。 - 将行为对象分配给文本视图的
layoutManager.delegate
和textStorage.delegate
。这将启用自动附件管理。- 如果你的自定义文本视图已经需要一个不同的对象作为其布局管理器或文本存储的代理,您可以手动代理调用
layoutManager(_:, didCompleteLayoutFor:, atEnd:)
和textStorage(_:, didProcessEditing:, range:, changeInLength:)
代理方法,但请注意,SubviewAttachingTextViewBehavior
可能在未来需要更多方法。
- 如果你的自定义文本视图已经需要一个不同的对象作为其布局管理器或文本存储的代理,您可以手动代理调用
- 重写文本视图的
textContainerInset
属性设置器,并调用附件行为中的layoutAttachedSubviews()
方法。这确保了当容器内边距更改时,附件布局得到更新。
附加子视图
要在文本中嵌入视图,请执行以下操作
- 创建一个
SubviewTextAttachment
实例(Objective-C中的VVSubviewTextAttachment
),并使用视图对象初始化它,可选地提供附件的大小。- 如果你没有明确提供大小,附件将尝试使用视图的拟合大小(使用自动布局计算),如果无法计算非零拟合大小,则退回到视图的当前大小。
- 或者,使用视图提供者初始化附件:一个遵守
TextAttachedViewProvider
协议(Objective-C中的VVTextAttachedViewProvider
)的对象。使用视图提供者允许用附件渲染属性为字符串,在多个文本视图中同时渲染,每个文本视图接收从视图提供者收到的表示附件的视图的实例。TextAttachedViewProvider
还可以在文本布局期间自定义附加视图的大小。 - 使用其
init(attachment:)
初始化器从附件创建一个NSAttributedString
。 - 将生成的字符串插入到您的属性文本中,并分配给文本视图(either
SubviewAttachingTextView
或嵌入了SubviewAttachingTextViewBehavior
的自定义文本视图)。 - 附加和移除附加的子视图会自动管理。如果您想移除嵌入的子视图,只需从文本视图的属性文本中移除相应的附件。
- 如果您的文本视图可编辑,用户也可以像删除其他文本一样删除附件。
限制
- 目前不支持在可编辑的文本视图中使用粘贴板操作(复制、剪切、粘贴)与子视图附件。
- 如果附加视图的本征大小发生变化,文本布局不会自动更新。目前,要改变附加子视图的大小,布局管理器需要通知无效布局并在相应的字符范围内显示,或者需要从文本属性中移除附件然后再添加回来。
许可
此库可在MIT许可下使用。有关更多信息,请参阅LICENSE
文件。