Ограничение автоматической компоновки на CALayer IOS

Привет, Я разрабатываю приложение для iPhone, в котором я попытался установить одну сторону границы для edittext. Я сделал это следующим образом:
 int borderWidth = 1;
CALayer *leftBorder = [CALayer layer];

leftBorder.borderColor = [UIColor whiteColor].CGColor;
leftBorder.borderWidth = borderWidth;

leftBorder.frame = CGRectMake(0, textField.frame.size.height - borderWidth, textField
                              .frame.size.width, borderWidth);
[textField.layer addSublayer:leftBorder];

Я установил некоторые ограничения на мой edittext в IB, так что, когда я поворачиваю свое устройство, он будет регулировать ширину текстового поля в соответствии с этим. Моя проблема в том, что настройка ширины edittext не регулирует ширину CALayer, которую я установил для своего текста редактирования. Поэтому я думаю, что я должен установить некоторые ограничения для моего объекта CALayer. Но я не знаю, как это сделать. Кто-нибудь знает об этом? Нужна помощь. Спасибо.

Ответ 1

весь бизнес авторезистентности зависит от вида. слои не авторезистируются.

что вам нужно сделать - в коде - изменить размер слоя самостоятельно

например.

в viewController вы бы сделали

- (void) viewDidLayoutSubviews {
  [super viewDidLayoutSubviews]; //if you want superclass behaviour... 
  // resize your layers based on the view new frame
  self.editViewBorderLayer.frame = self.editView.bounds;
}

или в пользовательском UIView вы можете использовать

- (void)layoutSubviews {
  [super layoutSubviews]; //if you want superclass behaviour...  (and lay outing of children)
  // resize your layers based on the view new frame
  layer.frame = self.bounds;
}

Ответ 2

Оформить это решение. Используйте KVO для пути "YourView.bounds", как показано ниже.

self.addObserver(self, forKeyPath: "YourView.bounds", options: .New, context: nil)

Затем обработайте его, как показано ниже.

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        if (keyPath == "YourView.bounds") {
            YourLayer.frame = YourView.bounds
            return
        }
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
    }

Для получения дополнительной информации см. следующую ссылку.

https://theswiftdev.com/2015/03/28/auto-layout-with-layers/

Ответ 3

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

-(void)layoutSubviews{
      sublayer1.frame = self.layer.bounds;
}

Ответ 4

В соответствии с ответом this layoutSubviews не вызывается во всех необходимых случаях. Я нашел этот метод делегата более эффективным:

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self != nil) {
        [self.layer addSublayer:self.mySublayer];
    }
    return self;
}

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

Ответ 5

У меня была аналогичная проблема: мне нужно установить кадр "CALayer" при использовании автоматической компоновки с представлениями (в коде, а не в IB).

В моем случае у меня была слегка свернутая иерархия, имеющая контроллер вида в контроллере представления. Я закончил этот вопрос SO и рассмотрел подход использования viewDidLayoutSubviews. Это не сработало. На всякий случай ваша ситуация похожа на мою, вот что я нашел...

Обзор

Я хотел установить фрейм для CAGradientLayer для UIView, который я позиционировал как subview внутри UIViewController с использованием ограничений автоматического макета.

Вызовите subview gradientView и контроллер вида child_viewController.

child_viewController был контроллером представления, который я бы установил как своего рода повторно используемый компонент. Таким образом, view of child_viewController составлялся в родительский контроллер представления - вызывают это parent_viewController.

Когда был вызван viewDidLayoutSubviews of child_viewController, frame of gradientView еще не установлен.

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

Итак, я перешел к использованию viewDidAppear. Однако из-за вложенности child_viewController я обнаружил, что viewDidAppear не вызывался.

(См. этот вопрос SO: viewWillAppear, viewDidAppear не вызывается, а не стреляет).

Мое текущее решение

Я добавил viewDidAppear в parent_viewController и оттуда я звоню viewDidAppear в child_viewController.

Для начальной загрузки мне нужно viewDidAppear, как это было до тех пор, пока в child_viewController не будет вызвано, что все подзадачи имеют свои фреймы. Затем я могу установить рамку для CAGradientLayer...

Я сказал, что это мое текущее решение, потому что я не очень доволен этим.

После первоначальной установки фрейма CAGradientLayer - этот кадр может стать недействительным, если изменяется макет. вращение устройства.

Чтобы справиться с этим, я использую viewDidLayoutSubviews в child_viewController -, чтобы сохранить кадр CAGradientLayer внутри gradientView, исправить.

Он работает, но не чувствует себя хорошо. (Есть ли лучший способ?)