web-dev-qa-db-ja.com

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];

IBの編集テキストにいくつかの制約を設定して、デバイスを回転させると、それに応じてテキストフィールドの幅が調整されるようにします。私の問題は、編集テキストに設定したCALayerの幅を調整せずに、編集テキストの幅を調整することです。したがって、CALayerアイテムにもいくつかの制約を設定する必要があると思います。しかし、私はそれを行う方法を知りません。これについて知っている人はいますか?助けが必要。ありがとうございました。

72
nilkash

自動サイズ変更ビジネス全体がビュー固有です。レイヤーは自動サイズ変更されません。

コードで行う必要があるのは、自分でレイヤーのサイズを変更することです

例えば.

あなたがする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;
}
117
Daij-Djan

このソリューションをチェックしてください。以下に示すように、パス「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/

8
arango_86

カスタムビューのメソッドlayoutSubviewsを実装しました。このメソッド内では、サブビューのレイヤーの現在の境界に一致するように各サブレイヤーのフレームを更新するだけです。

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

this answerによると、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;
}
4
pckill

破線枠で作成するときの私の解決策

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
   }
}
3
Marosdee Uma

Swift 3.x KVO Solution(@ 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
    )
}
0
footyapps27