首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不规则形状的UITextView中将文本垂直居中

在不规则形状的UITextView中将文本垂直居中
EN

Stack Overflow用户
提问于 2016-04-07 18:19:50
回答 2查看 421关注 0票数 1

我的工作是在圆形或椭圆形区域的中心渲染文本。理想情况下,我希望文本在垂直和水平方向居中,但让它在区域边界自然流动。

我发现了一种使用带有排除路径的UITextViewNSTextContainer的方法,它可以很好地在给定的垂直偏移量上布局文本,水平居中(代码如下)。但是,我不确定如何实现垂直居中。

我见过的所有方法都建议在文本布局和最终高度已知后调整文本视图的contentInset。(例如,this question)但是,对于形状不规则的区域,布局后文本的高度将取决于区域布局的起始位置。

我考虑过的一种方法是重试布局过程,直到获得满意的布局。有没有人用这种方法取得了成功?这里的一个挑战是,我还没有弄清楚如何确定是否所有文本都已在视图中呈现(即是否有足够的空间来布局所有文本)-在使用UITextView时,是否有方法查询是否所有内容都已“呈现”?

最后:这只是为了显示文本-不需要允许用户编辑视图的内容。在这种情况下,CoreText可能是更好的方法吗?

我是iOS开发的新手,所以如果我正在做任何离谱的事情,那也会很有帮助!

谢谢!

代码语言:javascript
复制
let boundingRect = CGRect(...)
let textView = UITextView(frame: boundingRect)

textView.editable = false
view.addSubview(textView)

let verticalInset:CGFloat = <some value>

let width = boundingRect.width
let height = boundingRect.height
let textBounds = CGSize(width: width, height:height - 2*verticalInset)
textView.bounds = textBounds

let exclusionRect = CGRect(x:0, y:-verticalInset, width:width, height:height)

let textRegion = UIBezierPath(ovalInRect: exclusionRect)    
let exclusionPath = UIBezierPath(rect:exclusionRect)
exclusionPath.appendPath(textRegion.bezierPathByReversingPath())

textView.textContainer.exclusionPaths = [exclusionPath]

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Center

let attributes = [NSParagraphStyleAttributeName: paragraphStyle]
let formattedContent = NSAttributedString(string: "....", attributes:attributes)

textView.attributedText(formattedContent)

下面是一张图片,如果对你有帮助的话,可以帮助你可视化上面的内容:

EN

回答 2

Stack Overflow用户

发布于 2016-05-12 22:32:55

如果您在矩形区域中布局文本,则很容易在之后通过向上或向下移动它来垂直居中。如果区域不是矩形,这是不可能的,因为文本在垂直移动后不一定适合形状。

我相信解决这个问题的方法总是迭代的方法。例如:在具有递增插入的形状中呈现文本,并找到最大的插入,以便文本适合结果形状。

要对核心文本执行此操作,可以为文本布局创建一个CTFrame,如下所示:

代码语言:javascript
复制
let text:NSAttributedString = ... // The text to render
let path:CGPath = ... // Bounds the shape in which the text is rendered
let framesetter = CTFramesetterCreateWithAttributedString(text)
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, nil)

使用此frame,您可以检查是否呈现了整个字符串:

代码语言:javascript
复制
let range = CTFrameGetVisibleStringRange(frame)
if text.length == range.length {
  // Fits
}

并呈现文本:

代码语言:javascript
复制
let ctx:CGContext = ... 
CTFrameDraw(renderFrame, ctx)

如果需要有关呈现文本的更多详细信息,可以使用CTFrameGetLinesframe获取CTLine。然后,使用带有选项UseGlyphPathBoundsUseOpticalBoundsCTFrameGetLineOriginsCTLineGetBoundsWithOptions,您可以计算单条线路的光学边界。这允许更精确的垂直调整。(准备好学习一些线性代数,直接在CoreGraphics中使用CoreText所需的坐标系转换可能有点繁琐)。

票数 2
EN

Stack Overflow用户

发布于 2016-04-08 03:18:44

在这里我不能给出一个很棒的答案。

不过,我刚刚尝试过YYText。它有一个支持垂直文本对齐和排除路径的"YYLabel“。看看他们的演示项目,特别是他们的表视图中演示的'TextAttributes1‘行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36473247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档