it-roy-ru.com

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

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

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

88
Geri

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

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

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

129
Chadwick Wood

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

24
Ole Begemann

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

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

super.layoutSublayersOfLayer(layer)
}

Работает для меня.

11
Runo Sahara

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

Что-то вроде этого:

-(void)layoutSubviews{
   //keep the same Origin, just update the width and height
   if(sublayer1!=nil){
      sublayer1.frame = self.layer.bounds;
   }
}
9
Solin

Swift 3 версия  

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

Объявить первым

let gradientLayer: CAGradientLayer = CAGradientLayer()

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

override func layoutSubviews() {
    gradientLayer.frame = self.YourCustomView.bounds
}
4
Vinay Krishna Gupta

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.

3
Fattie

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

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

или (начиная с iOS 8)

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