2016-04-07 6 views
1

Я работаю над текстом рендеринга в центре круглой или овальной формы. В идеале, я бы хотел сосредоточить текст по вертикали и горизонтали, но естественным образом он протекает на границах региона.Вертикально центрирующий текст в нерегулярной форме UITextView

Я нашел подход, используя UITextView и NSTextContainer с исключениями, которые делают хорошую работу по выкладке текста при заданном вертикальном смещении, центрированном по горизонтали (код ниже). Однако я не уверен, как добиться вертикального центрирования.

Подходы, которые я видел все, предлагают корректировку contentInset текстового вида после того, как текст был выложен, а конечная высота известна. (Например, this question) Однако в случае области неправильной формы высота текста после его выделения будет зависеть от того, где начинается расположение области.

Подход, который я рассмотрел, заключается в том, чтобы повторить процесс компоновки до тех пор, пока не будет достигнута удовлетворительная компоновка. Кто-нибудь имел успех с таким подходом? Одна из проблем заключается в том, что я не определил, как определить, был ли весь текст визуализирован в представлении (т. Е. Имеется ли достаточно места для размещения всего текста) --- существует ли способ запроса, все ли содержимое был «оказан» при использовании UITextView?

И наконец: это только для отображения текста --- нет необходимости разрешать пользователю редактировать содержимое представления. Может быть, лучший способ в этом случае - CoreText?

Я довольно новичок в разработке iOS, поэтому, если есть что-то возмутительное, что я делаю, это также было бы полезно знать!

Спасибо!

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) 

Вот изображение, чтобы помочь себе выше, если полезно: example

+0

Это именно то, что я сейчас пытаюсь выработать! Я думаю, что TextKit может быть единственным способом. –

ответ

0

Я не могу предложить фантастический ответ здесь.

Однако, я только что опросил YYText. У этого есть «YYLabel», который поддерживает вертикальное выравнивание текста и пути исключения. Взгляните на их демонстрационный проект, в частности на строку «TextAttributes1» в их табличном представлении.

+0

Большое спасибо за предложение @ Кристофер. Я проверю это. На самом деле, мне также удалось найти работоспособное решение для моей утилизации - не красивое, но прекрасное на данный момент - которое я опубликую ниже. Ура! – duncanm

+0

Oop - должен добавить: однажды у меня была возможность проверить YYText, отметит ваш ответ. – duncanm

1

Если вы выкладываете текст в прямоугольной области, его можно легко центрировать по вертикали, сдвинув его вверх или вниз. Если область не прямоугольная, как в вашем случае, это невозможно, так как текст не обязательно вписывается в форму после того, как вы сдвинете ее по вертикали.

Я считаю, что решение этого метода всегда является итерационным. Например: визуализируйте текст в форме с увеличением вставки и найдите самую большую вставку, чтобы текст соответствовал полученной форме.

Чтобы сделать это с помощью основного текста, вы можете создать CTFrame для размещения текста, как это:

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, вы можете проверить, если вся строка была оказана:

let range = CTFrameGetVisibleStringRange(frame) 
if text.length == range.length { 
    // Fits 
} 

И для отображения текста:

let ctx:CGContext = ... 
CTFrameDraw(renderFrame, ctx) 

Если вы необходимо получить более подробную информацию о визуализированном тексте, вы можете использовать CTFrameGetLines, чтобы получить CTLine с frame. Затем, используя CTFrameGetLineOrigins и CTLineGetBoundsWithOptions с опцией UseGlyphPathBounds или UseOpticalBounds, вы можете рассчитать оптические границы для отдельных линий. Это позволяет выполнить более точную вертикальную настройку. (Приготовьтесь к некоторой линейной алгебре, преобразования системы координат, которые необходимы для непосредственного использования CoreText с CoreGraphics, могут быть немного утомительными).

Смежные вопросы