Auto Layout Limit on CALayer IOS

Hi, I am developing an iPhone application in which I tried to set one side of the border for edittext. I did it as follows:
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]; 

I set some restrictions on my edittext in IB, so that when I rotate my device, it will adjust the width of the text box to suit this. My problem is that adjusting the width of the edittext does not adjust the width of the CALayer that I set for my edit text. Therefore, I think I should set some restrictions for my CALayer object. But I do not know how to do this. Does anyone know about this? Help is needed. Thank.

+44
ios autolayout calayer
Jun 19 '14 at 9:30
source share
5 answers

the entire autoresistance business depends on the species. layers are not autoresist.

what you need to do - in the code - resize the layer yourself

eg.

in viewController you would do

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

or in a custom UIView you can use

 - (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; } 
+94
Jun 19 '14 at 9:35
source share
β€” -

To issue this decision. Use KVO for the "YourView.bounds" path, as shown below.

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

Then process it as shown below.

 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) } 

See the following link for more information.

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

+5
Jan 26 '17 at 7:06 on
source share

I implemented the layoutSubviews method of my custom view; inside this method, I just update each sublayer frame to fit the current boundaries of my subview level.

 -(void)layoutSubviews{ sublayer1.frame = self.layer.bounds; } 
+2
Jul 01 '14 at 1:47
source share

According to the answer, this layoutSubviews not called in all necessary cases. I found this delegate method more efficient:

 - (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; } 
+1
Oct 23 '17 at 13:32
source share

I had a similar problem: I need to set the "CALayer" frame when using automatic layout with views (in code, not in IB).

In my case, I had a slightly collapsed hierarchy having a view controller in the view controller. I ended this SO question and reviewed the approach of using viewDidLayoutSubviews . This did not work. Just in case, your situation is similar to mine, that's what I found ...

Overview

I wanted to set the frame for the CAGradientLayer for UIView , which I positioned as a subview inside the UIViewController using the automatic layout restrictions.

Call the subview gradientView and the view controller child_viewController .

child_viewController was a view controller that I would set as a kind of reusable component. Thus, the view of child_viewController was compiled into the parent view controller - this is called parent_viewController .

When viewDidLayoutSubviews of child_viewController was called, the frame of gradientView has not yet been set.

(At this point, I would recommend sprinkling some NSLog statements to get an idea of ​​the sequence of creating views in your hierarchy, etc.)

So, I switched to using viewDidAppear . However, due to the nesting of child_viewController I found that viewDidAppear not called.

(See this SO question: viewWillAppear, viewDidAppear is not called, not fired ).

My current solution

I added viewDidAppear to parent_viewController and from there I call viewDidAppear to child_viewController .

For bootstrap, I need viewDidAppear , as it was until in child_viewController it was called that all subtasks have their frames. Then I can set the frame for CAGradientLayer ...

I said that this is my current decision because I am not very happy with it.

After the initial installation of the CAGradientLayer frame, this frame may become invalid if the layout changes. device rotation.

To handle this, I use viewDidLayoutSubviews in child_viewController - to save the CAGradientLayer frame inside gradientView , fix it.

It works, but does not feel well. (Is there a better way?)

-2
May 2 '15 at 23:56
source share



All Articles