CALayers не были изменены при изменении границ своего UIView. Зачем? - PullRequest
92 голосов
/ 24 марта 2010

У меня есть UIView, к которому добавлено около 8 различных CALayer подслоев. Если я изменяю границы представления (анимированный), то само представление уменьшается (я проверил это с помощью backgroundColor), но размер подслоев остается неизменным .

Как это решить?

Ответы [ 7 ]

135 голосов
/ 04 ноября 2010

Я использовал тот же подход, что и Солин, но в этом коде есть опечатка. Метод должен быть:

- (void)layoutSubviews {
  [super layoutSubviews];
  // resize your layers based on the view's new bounds
  mylayer.frame = self.bounds;
}

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

24 голосов
/ 24 марта 2010

Поскольку CALayer на iPhone не поддерживает диспетчеры компоновки, я думаю, что вы должны сделать основной слой своего представления пользовательским подклассом CALayer, в котором вы переопределяете layoutSublayers, чтобы установить кадры всех подслоев. Вы также должны переопределить метод +layerClass вашего представления, чтобы вернуть класс вашего нового подкласса CALayer.

11 голосов
/ 27 февраля 2015

Я использовал это в UIView.

-(void)layoutSublayersOfLayer:(CALayer *)layer
{
    if (layer == self.layer)
    {
        _anySubLayer.frame = layer.bounds;
    }

super.layoutSublayersOfLayer(layer)
}

У меня работает.

9 голосов
/ 28 июля 2010

У меня была такая же проблема. В слой пользовательского вида я добавил еще два подслоя. Чтобы изменить размер подслоев (каждый раз, когда изменяются границы пользовательского представления), я реализовал метод layoutSubviews моего пользовательского представления; внутри этого метода я просто обновляю кадр каждого подслоя, чтобы соответствовать текущим границам слоя моего подпредставления.

Примерно так:

-(void)layoutSubviews{
   //keep the same origin, just update the width and height
   if(sublayer1!=nil){
      sublayer1.frame = self.layer.bounds;
   }
}
5 голосов
/ 11 декабря 2017

2017

Дословный ответ на этот вопрос:

"CALayers не были изменены при изменении границ своего UIView. Почему?"

в лучшую или худшую сторону

needsDisplayOnBoundsChange

по умолчанию имеет значение false в CALayer.

решение

class CircularGradientViewLayer: CALayer {

    override init() {

        super.init()
        needsDisplayOnBoundsChange = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override open func draw(in ctx: CGContext) {
        go crazy drawing in .bounds
    }
}

Действительно, я направляю вас к этому QA

https://stackoverflow.com/a/47760444/294884

, который объясняет, что, черт возьми, делает критическая настройка contentsScale; вам обычно нужно в равной степени установить это при установке needsDisplayOnBoundsChange.

4 голосов
/ 08 июня 2017

Версия Swift 3

В пользовательской ячейке добавить следующие строки

Объявите сначала

let gradientLayer: CAGradientLayer = CAGradientLayer()

Затем добавьте следующие строки

override func layoutSubviews() {
    gradientLayer.frame = self.YourCustomView.bounds
}
0 голосов
/ 01 марта 2015

Как писал [Ole], CALayer не поддерживает автоматическое изменение размера на iOS. Таким образом, вы должны настроить макет вручную. Мой вариант заключался в настройке рамки слоя внутри (iOS 7 и более ранние версии)

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

или (с iOS 8)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinato
...