uitextview背景色
I have had the opportunity to learn so many things while working on Proton. Just as much as I like sharing my code, I also enjoy talking about the challenges and the wins. This article focuses on yet another feature in Proton which, I believe, should have been available out of the box in iOS. If you are new here and before diving into the details, would like to know more about Proton, Building a native editor for iOS is a good place to start.
在Proton工作期间,我有机会学习了很多东西。 就像我喜欢共享代码一样,我也喜欢谈论挑战和胜利。 本文着重介绍Proton的另一个功能,我认为应该在iOS中立即可用。 如果您是这里的新手,在开始探索细节之前,想了解有关Proton的更多信息,那么为iOS构建本机编辑器是一个不错的起点。
带有背景的文字 (Text with background)
Often there are times when we want to add background to the text in a text view. The most simplest, and probably best, approach is to use backgroundColor attribute. You can provide any UIColor
to a given range, and iOS takes care of rendering that color in the background of the text.
通常,有时候我们想在文本视图中为文本添加背景。 最简单,也可能最好的方法是使用backgroundColor属性。 您可以提供给定范围内的任何UIColor
,iOS负责在文本背景中呈现该颜色。
The only code you need is to add attribute backgroundColor: UIColor.cyan
to the list of NSAttributedString.Key
in the attributedText
property of UITextView
. While this works for most cases, it may feel too vanilla. You might want a fancier formatting like adding shadows or borders. At the very least, it is very likely that you would want rounded corners to the background. Unfortunately, none of these properties may be modified by just using attributes.
您唯一需要的代码是将属性backgroundColor: UIColor.cyan
添加到UITextView
的attributedText
属性中的NSAttributedString.Key
列表中。 尽管这在大多数情况下都有效,但可能会感觉太过香草。 您可能希望使用更高级的格式,例如添加阴影或边框。 至少,您很可能希望对背景进行圆角处理。 不幸的是,仅使用属性就不能修改这些属性。
更好的背景 (Better backgrounds)
One of the principles I am following with Proton is to provide all that, we as developers, might want to customize and yet keep those customizations natural. What I mean is that all the customizations that you might want to do, should ideally not take anything more than adding an attribute with required information. For e.g. if you want to add lists to a UITextView, it should be as simple as adding a .listItem
attribute to the range of text. You can read about my adventures with lists in Lists in UITextView. With Proton, you can add an attribute, very similar to backgroundColor
, and achieve the following:
我作为Proton遵循的原则之一就是为开发人员提供所有可能想要自定义但仍保持自然自定义的功能。 我的意思是,理想情况下,您可能要进行的所有自定义操作都不应只添加带有必需信息的属性。 例如,如果您要将列表添加到UITextView,则应像向文本范围添加.listItem
属性一样简单。 您可以在UITextView的“列表”中阅读有关我的冒险经历的列表。 使用Proton ,您可以添加一个非常类似于backgroundColor
的属性,并实现以下目的:
The only code you need to add is:
您需要添加的唯一代码是:
let style = BackgroundStyle(color: .green, cornerRadius: 5,
border: BorderStyle(lineWidth: 1, color: UIColor.blue),
shadow: ShadowStyle(color: .gray, offset: CGSize(width: 2, height: 2), blur: 3))editor.addAttribute(.backgroundStyle, value: style, at: editor.selectedRange)
editor
is the Proton counterpart for UITextView
. Besides other features, it provides simple API to manipulate attributes.
editor
是UITextView
的Proton对应项。 除了其他功能,它还提供了简单的API来操纵属性。
引擎盖下 (Under the hood)
If you want to understand how this has been achieved in Proton, please read on.
如果您想了解Proton是如何实现的,请继续阅读。
The layout and drawing of text is managed by NSLayoutManager
. It provides two functions that can be overridden to achieve the desired behaviour:
文本的布局和图形由NSLayoutManager
管理。 它提供了两个可以重写以实现所需行为的功能:
初始方法 (Initial approach)
The first approach I tried was using fillBackgroundRectArray. This function provides a finer control over drawing the background for the ranges with .backgroundColor
attribute. This function gets invoked with all the rectangles defining the range with background color.
我尝试的第一种方法是使用fillBackgroundRectArray 。 此功能可更好地控制使用.backgroundColor
属性绘制背景范围的背景。 所有定义背景颜色范围的矩形均会调用此函数。
This approach works, but depending upon how content is added, fillBackgroundRectArray may be called multiple times even for the text that is in the same line. This results in rendering rounded corners based on words instead of lines of text:
这种方法有效,但是取决于内容的添加方式,即使对于同一行中的文本,也可以多次调用fillBackgroundRectArray 。 这导致基于单词而不是文本行渲染圆角:
If the content is pasted instead of being typed, the background is drawn as expected with no visible rounding per word as we see above.
如果粘贴内容而不是键入内容,则会如预期那样绘制背景,并且每个单词都没有可见的舍入,如我们上面看到的。
最终方法 (Final approach)
Spending a little more time with NSLayoutManager
, I figured out that using drawBackground
is a better option. Using similar code as above, you can achieve better results.
我花了更多的时间在NSLayoutManager
,我发现使用drawBackground
是更好的选择。 使用上面类似的代码,可以获得更好的结果。
In Proton, I added additional logic to calculate the rounded corners based on each of the lines that are overlapping and also used a trick that ensures that when there are borders, the borders are only drawn on outer edges of the rectangles with background.
在Proton中 ,我添加了其他逻辑以根据重叠的每条线计算圆角,还使用了一种技巧来确保当有边界时,仅在具有背景的矩形的外边缘上绘制边界。
The initial version with all the selected range looked like the following where the corners are rounded at outer edges, but there is still bottom line of the first rectangle that is causing this to appear as two separate background rectangles.
带有所有选定范围的初始版本如下所示,其中的角在外边缘处是圆角的,但是第一个矩形的底线仍然导致其显示为两个单独的背景矩形。
Using some simple logic, I was able to calculate the overlapping line, which is shown in yellow color below:
使用一些简单的逻辑,我能够计算出重叠线,该重叠线以黄色显示如下:
Once the overlapping line is identified, the only other thing that is left is to use the same color for the line as that for the background, so that the line disappears:
一旦识别出重叠的线,剩下的唯一一件事就是对该线使用与背景相同的颜色,以便该线消失:
还有一件事 (One more thing)
With all the calculations that are put in place to draw background with rounded corners, it also helps drawing the background dynamically where it merges and splits the background based on the range of text having the backgroundStyle
applied:
使用所有计算来绘制带有圆角的背景时,它还有助于动态绘制背景,并根据应用了backgroundStyle
的文本范围在其中合并和拆分背景的地方:
I hope you enjoyed reading about this just as much as I enjoyed developing this feature in Proton.
希望您喜欢阅读此书,就像我喜欢在Proton中开发此功能一样。
翻译自: https://levelup.gitconnected.com/background-with-rounded-corners-in-uitextview-1c095c708d14
uitextview背景色