Может ли CAShapeLayer формировать центр в подвиде? - PullRequest
0 голосов
/ 08 сентября 2018

Я создал произвольное представление

let middleView = UIView(
    frame: CGRect(x: 0.0,
                  y: view.frame.height/4,
                  width: view.frame.width,
                  height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
view.addSubview(middleView)

Затем я создал круг, используя UIBezierPath; однако, когда я устанавливаю положение в middleView.center, круг находится далеко от нижней части вида. Можете ли вы установить положение в центре подпредставления?

iPhone 8 Plus with view and uncentered circle

let shapeLayer = CAShapeLayer()
let circlePath = UIBezierPath(
        arcCenter: .zero,
        radius: 100,
        startAngle: CGFloat(0).toRadians(),
        endAngle: CGFloat(360).toRadians(),
        clockwise: true)
shapeLayer.path = circlePath.cgPath
shapeLayer.strokeColor = UIColor.purple.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.position = middleView.center
middleView.layer.addSublayer(shapeLayer)

Как мне центрировать этот круг в этом виде?

1 Ответ

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

У вас две проблемы.

Сначала вы устанавливаете shapeLayer.position = middleView.center. center вида - это геометрия суперпредставления. Другими словами, middleView.center относится к view, а не к middleView. Но затем вы добавляете shapeLayer в качестве подслоя middleView.layer, что означает, что shapeLayer нужен position, который находится в геометрии middleView, а не в геометрии view. Вам нужно установить shapeLayer.position в центр middleView.bounds:

shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)

Во-вторых, вы не сказали, где вы все это делаете. Я думаю, вы делаете это в viewDidLoad. Но это слишком рано. В viewDidLoad представления, загруженные из раскадровки, по-прежнему имеют кадры, которые им были даны в раскадровке, и еще не были выложены для размера экрана текущего устройства. Поэтому не стоит смотреть на frame (или bounds или center) в viewDidLoad, если вы не сделаете что-то, чтобы убедиться, что все будет правильно выложено на этапе макета. Обычно вы делаете это, устанавливая autoresizingMask или создавая ограничения. Пример: * * тысяча двадцать-шесть

let middleView = UIView(
    frame: CGRect(x: 0.0,
                  y: view.frame.height/4,
                  width: view.frame.width,
                  height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
middleView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
view.addSubview(middleView)

Однако shapeLayer не принадлежит представлению, поэтому он не имеет autoresizingMask и не может быть ограничен. Вы должны выложить это в коде. Вы можете сделать это, но лучше всего использовать представление для управления слоем формы. Таким образом, вы можете использовать autoresizingMask или ограничения для управления макетом фигуры, и вы можете установить его в viewDidLoad.

    let circleView = CircleView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
    circleView.center = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
    circleView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
    circleView.shapeLayer.strokeColor = UIColor.purple.cgColor
    circleView.shapeLayer.fillColor = nil
    middleView.addSubview(circleView)

...

class CircleView: UIView {
    override class var layerClass: AnyClass { return CAShapeLayer.self }

    var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer }

    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
    }

}

Результат:

demo

А после поворота в ландшафт:

demo in landscape

...