Это ошибка прозрачности UITextView? - PullRequest
0 голосов
/ 24 августа 2018

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

Проблема, по-видимому, является результатом использования метода boundingRect NSLayoutManager для получения (среди прочего) отдельных значений ширины символов, а затем использования этих значений для установки свойств ширины кадра UITextView символов. Это, очевидно, приводит к игнорированию установки backgroundColor текстового представления в UIColor.clear (то есть фон становится непрозрачным). Приведенный ниже код игровой площадки воспроизводит проблему, показанную красным текстом , и показывает обходной путь использования константы для ширины в черном . Чем плотнее кернинг, тем сильнее выражен эффект.

enter image description here

Это ошибка? Или это причуды из-за чего-то еще?

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {

    override func loadView() {

        let view = UIView()
        view.bounds = CGRect(x: -100, y: -100, width: 200, height: 200)
        view.backgroundColor = .white

        let str = "..T.V.W.Y.."

        let strStorage = NSTextStorage(string: str)
        let layoutManager = NSLayoutManager()
        strStorage.addLayoutManager(layoutManager)
        let textContainer = NSTextContainer(size: view.bounds.size)
        textContainer.lineFragmentPadding = 0.0
        layoutManager.addTextContainer(textContainer)

        let strArray = Array(str)

        struct CharInfo {
            var char: Character
            var origin: CGPoint?
            var size: CGSize?
        }

        var charInfoArray = [CharInfo]()

        for index in 0..<str.count {

            charInfoArray.append(CharInfo.init(char: strArray[index], origin: nil, size: nil))
            let charRange = NSMakeRange(index, 1)
            let charRect = layoutManager.boundingRect(forGlyphRange: charRange, in: textContainer)
            charInfoArray[index].origin = charRect.origin
            charInfoArray[index].size = charRect.size
        }

        for charInfo in charInfoArray {

            let textView0 = UITextView()
            textView0.backgroundColor = UIColor.clear // Ignored in this case!!
            textView0.text = String(charInfo.char)
            textView0.textContainerInset = UIEdgeInsets.zero
            let size0 = charInfo.size!
            textView0.frame = CGRect(origin: charInfo.origin!, size: size0)
            textView0.textContainer.lineFragmentPadding = CGFloat(0.0)
            textView0.textColor = UIColor.red
            view.addSubview(textView0)

            let textView1 = UITextView()
            textView1.backgroundColor = UIColor.clear // Required
            textView1.text = String(charInfo.char)
            textView1.textContainerInset = UIEdgeInsets.zero
            var size1 = charInfo.size!
            size1.width = 20 // But changing .height has no effect on opacity
            textView1.frame = CGRect(origin: charInfo.origin!, size: size1)
            textView1.frame = textView1.frame.offsetBy(dx: 0, dy: 20)
            textView1.textContainer.lineFragmentPadding = CGFloat(0.0)
            textView1.textColor = UIColor.black
            view.addSubview(textView1)
        }

        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

1 Ответ

0 голосов
/ 08 сентября 2018

Это похоже на ошибку, но это с помощью метода экземпляра NSLayoutManager boundingRect (forGlyphRange: in :). Это только выглядит как будто это может быть изменение прозрачности.

Согласно документации Apple boundingRect (forGlyphRange: in :) должен "[возвращать] один ограничивающий прямоугольник (в координатах контейнера), содержащий все глифы и другие метки, нарисованные в данном текстовом контейнере для заданный диапазон глифов, включая глифы, которые рисуют вне своих прямоугольников фрагментов строки и текстовые атрибуты, такие как подчеркивание. " Но это не то, что он делает.

В этом случае ширина каждого boundingRect уменьшается на величину, на которую следующий глиф был смещен влево из-за кернинга. Вы можете проверить это, например, используя str = "ToT" и добавив print (size0.width) сразу после его установки. Вы получите это:

6.0         // "T"; should have been 7.330078125
6.673828125 // "o"
7.330078125 // "T"

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

...