Добавление того же слоя в подпредставление изменяет его визуальное положение.

avatar
Kalzem
8 апреля 2018 в 10:49
135
2
0

Я добавил подвид (с черной рамкой) в вид и отцентрировал его.

Затем я создаю 2 одинаковых треугольника с помощью CAShapeLayer и добавляю один в подвид, а другой в основной вид.

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

Playground result

А вот код:

let view = UIView()
let borderedView = UIView()
var containedFrame = CGRect(x: 0, y: 0, width: 100, height: 100)

func setupUI() {
    view.frame = CGRect(x: 0, y: 0, width: 300, height: 600)
    view.backgroundColor = .white
    borderedView.frame = containedFrame
    borderedView.center = view.center
    borderedView.backgroundColor = .clear
    borderedView.layer.borderColor = UIColor.black.cgColor
    borderedView.layer.borderWidth = 1
    view.addSubview(borderedView)
    setupTriangles()
}

private func setupTriangles() {
    view.layer.addSublayer(createTriangle(color: .red)) // RED triangle
    borderedView.layer.addSublayer(createTriangle(color: .green)) // GREEN triangle
}

private func createTriangle(color: UIColor) -> CAShapeLayer {
    let layer = CAShapeLayer()
    let bezierPath = UIBezierPath()
    bezierPath.move(to: CGPoint(x: 0, y: 0))
    bezierPath.addLine(to: CGPoint(x: -containedFrame.width, y: 0))
    bezierPath.addLine(to: CGPoint(x: 0, y: -containedFrame.height))
    bezierPath.close()
    layer.position = borderedView.center
    layer.path = bezierPath.cgPath
    layer.fillColor = color.cgColor
    return layer
}

Примечание: Все position (вида, borderedView и оба треугольника) одинаковы (150.0, 300.0)

Вопрос: Почему зеленый слой находится не в том положении?

Источник

Ответы (2)

avatar
vacawama
8 апреля 2018 в 12:35
3

@DuncanC прав в том, что каждый вид имеет свою собственную систему координат. Ваша проблема в этой строке:

layer.position = borderedView.center

Это устанавливает положение слоя в центр кадра для borderedView, который находится в системе координат view. При создании зеленого треугольника необходимо использовать систему координат borderedView.

.

Это можно исправить, передав представление в функцию createTriangle, а затем используя центр bounds этого представления в качестве положения слоя:

private func setupTriangles() {
    view.layer.addSublayer(createTriangle(color: .red, for: view)) // RED triangle
    borderedView.layer.addSublayer(createTriangle(color: .green, for: borderedView)) // GREEN triangle
}

private func createTriangle(color: UIColor, for view: UIView) -> CAShapeLayer {
    let layer = CAShapeLayer()
    let bezierPath = UIBezierPath()
    bezierPath.move(to: CGPoint(x: 0, y: 0))
    bezierPath.addLine(to: CGPoint(x: -containedFrame.width, y: 0))
    bezierPath.addLine(to: CGPoint(x: 0, y: -containedFrame.height))
    bezierPath.close()
    layer.position = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
    layer.path = bezierPath.cgPath
    layer.fillColor = color.cgColor
    return layer
}

Примечание: при этом зеленый треугольник появляется прямо под красным, поэтому его не видно.

Duncan C
8 апреля 2018 в 13:43
0

Молодец, что нашел "дымящийся пистолет", вызвавший конкретное поведение. (проголосовал.) Я не внимательно смотрел на код ОП.

vacawama
8 апреля 2018 в 13:54
0

Спасибо @DuncanC. Мне весело работать над визуальными проблемами, когда ОП предоставляет свой код.

Duncan C
8 апреля 2018 в 21:10
0

Итак, вы копировали/вставляли код в проект или игровую площадку и отлаживали его, или вы просматривали код вручную?

vacawama
8 апреля 2018 в 21:34
0

@DuncanC, я просмотрел код вручную и определил проблемную строку. Я не идентифицировал проблему, распечатывая значения или выполняя код. Затем я поместил код в проект и разработал исправление. Конечно, помогло то, что я уже сталкивался с подобными проблемами.

avatar
Duncan C
8 апреля 2018 в 11:00
2

Каждый вид/слой использует систему координат своего супервида/суперслоя. Если вы добавите слой в self.view.layer, он будет расположен в системе координат self.view.layer. Если вы добавите слой в borderedView.layer, он будет находиться в системе координат borderedView.layer.

Подумайте об иерархии вида/слоя как о стопках листов миллиметровой бумаги. Вы помещаете новый лист бумаги на текущий фрагмент (супервид/слой) в системе координат текущего фрагмента, но затем, если вы рисуете на новом виде/слое или добавляете новые виды/слой внутри этого, вы используете новый система координат вида/слоя.

Kalzem
8 апреля 2018 в 12:04
0

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