CALayer IOS의 자동 레이아웃 제약
안녕하세요 저는 edittext에 대해 한쪽 테두리를 설정하려고 시도한 iPhone 응용 프로그램을 개발 중입니다. 나는 다음과 같은 방식으로 이것을했다.
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];
IB의 edittext에 몇 가지 제약을 두어 장치를 회전 할 때 그에 따라 텍스트 필드의 너비를 조정합니다. 내 문제는 편집 텍스트에 대해 설정 한 CALayer의 너비를 조정하지 않고 edittext의 너비를 조정한다는 것입니다. 따라서 CALayer 항목에도 몇 가지 제약을 두어야한다고 생각합니다. 그러나 나는 그것을하는 방법을 모른다. 이것에 대해 알고 있습니까? 도움이 필요하다. 감사합니다.
전체 자동 크기 조정 비즈니스는보기에 따라 다릅니다. 레이어는 자동 크기 조정되지 않습니다.
코드에서해야 할 일은 레이어의 크기를 직접 조정하는 것입니다.
예 :
viewController에서 당신은 할 것입니다
- (void) viewDidLayoutSubviews {
[super viewDidLayoutSubviews]; //if you want superclass's behaviour...
// resize your layers based on the view's new frame
self.editViewBorderLayer.frame = self.editView.bounds;
}
또는 사용자 정의 UIView에서 사용할 수 있습니다.
- (void)layoutSubviews {
[super layoutSubviews]; //if you want superclass's behaviour... (and lay outing of children)
// resize your layers based on the view's new frame
layer.frame = self.bounds;
}
이 솔루션을 확인하십시오. 아래와 같이 "YourView.bounds"경로에 KVO를 사용하십시오.
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/
내 사용자 정의보기의 layoutSubviews 메소드를 구현했습니다. 이 방법 내에서 내 하위 뷰 레이어의 현재 경계와 일치하도록 각 하위 레이어의 프레임을 업데이트합니다.
-(void)layoutSubviews{
sublayer1.frame = self.layer.bounds;
}
이 답변 에 따르면 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;
}
점선 테두리로 만들 때 내 솔루션
class DashedBorderView: UIView {
let dashedBorder = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
//custom initialization
dashedBorder.strokeColor = UIColor.red.cgColor
dashedBorder.lineDashPattern = [2, 2]
dashedBorder.frame = self.bounds
dashedBorder.fillColor = nil
dashedBorder.cornerRadius = 2
dashedBorder.path = UIBezierPath(rect: self.bounds).cgPath
self.layer.addSublayer(dashedBorder)
}
override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
dashedBorder.path = UIBezierPath(rect: self.bounds).cgPath
dashedBorder.frame = self.bounds
}
}
Swift 3.x KVO 솔루션 (@ arango_86의 답변 업데이트)
관찰자 추가
self.addObserver(
self,
forKeyPath: "<YOUR_VIEW>.bounds",
options: .new,
context: nil
)
값 관찰
override open func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?
) {
if (keyPath == "<YOUR_VIEW.bounds") {
updateDashedShapeLayerFrame()
return
}
super.observeValue(
forKeyPath: keyPath,
of: object,
change: change,
context: context
)
}
비슷한 문제가있었습니다. 뷰와 함께 자동 레이아웃을 사용할 때 'CALayer'프레임을 설정해야합니다 ( IB가 아닌 코드에서 ).
In my case, I had a slightly convoluted hierarchy, having a view controller within a view controller. I ended up at this SO question and looked into the approach of using viewDidLayoutSubviews
. That didn't work. Just in case your situation is similar to my own, here's what I found...
Overview
I wanted to set the frame for the CAGradientLayer
of a UIView
that I was positioning as a subview within a UIViewController
using auto layout constraints.
Call the subview gradientView
and the view controller child_viewController
.
child_viewController
was a view controller I'd set up as a kind of re-usable component. So, the view
of child_viewController
was being composed into a parent view controller - call that parent_viewController
.
When viewDidLayoutSubviews
of child_viewController
was called, the frame
of gradientView
was not yet set.
(At this point, I'd recommend sprinkling some NSLog
statements around to get a feel for the sequence of creation of views in your hierarchy, etc.)
So I moved on to try using viewDidAppear
. However, due to the nested nature of child_viewController
I found viewDidAppear
was not being called.
(See this SO question: viewWillAppear, viewDidAppear not being called, not firing).
My current solution
I've added viewDidAppear
in parent_viewController
and from there I'm calling viewDidAppear
in child_viewController
.
For the initial load I need viewDidAppear
as it's not until this is called in child_viewController
that all of the subviews have their frames set. I can then set the frame for the CAGradientLayer
...
I've said that this is my current solution because I'm not particularly happy with it.
After initially setting the frame of the CAGradientLayer
- that frame can become invalid if the layout changes - e.g. rotating the device.
To handle this I'm using viewDidLayoutSubviews
in child_viewController
- to keep the frame of the CAGradientLayer
within gradientView
, correct.
It works but doesn't feel good. (Is there a better way?)
참고URL : https://stackoverflow.com/questions/24303279/auto-layout-constraint-on-calayer-ios
'program tip' 카테고리의 다른 글
파이썬 : 줄이 빈 줄인지 확인하는 방법 (0) | 2020.10.24 |
---|---|
JBoss AS 7 : tmp를 정리하는 방법? (0) | 2020.10.24 |
프로세스에서 dex를 실행하려면 Gradle 데몬에 더 큰 힙이 필요합니다. (0) | 2020.10.24 |
__getitem__ 메서드 이해 (0) | 2020.10.24 |
왜 rake db : migrate : reset이 rake -T에 나열되지 않습니까? (0) | 2020.10.23 |