web-dev-qa-db-fra.com

Contrainte de mise en page automatique sur CALayer IOS

Bonjour, je développe une application iPhone dans laquelle j'ai essayé de définir un bord latéral pour edittext. Je l'ai fait de la manière suivante:

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

Je mets des contraintes sur mon edittext dans IB pour que, lorsque je fais pivoter mon appareil, il ajuste la largeur du champ de texte en fonction de cela. Mon problème est que cela ajuste la largeur de edittext et non celle de CALayer que j'ai définie pour mon texte d'édition. Je pense donc que je dois également imposer certaines contraintes à mon élément CALayer. Mais je ne sais pas comment faire ça. Tout le monde sait à ce sujet? Besoin d'aide pour. Je vous remercie.

63
nilkash

l'ensemble de la gestion des autoroutes est spécifique à la vue. les couches n'augmentent pas automatiquement.

ce que vous devez faire - dans le code - est de redimensionner vous-même le calque

par exemple. 

dans un viewController vous feriez

- (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;
}

ou dans un UIView personnalisé, vous pouvez utiliser

- (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;
}
110
Daij-Djan

Checkout this solution . Utilisez KVO, pour le chemin "YourView.bounds" comme indiqué ci-dessous.

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

Puis manipulez-le comme indiqué ci-dessous.

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

Pour plus d'informations, reportez-vous au lien suivant.

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

7
arango_86

J'ai implémenté la méthode layoutSubviews de ma vue personnalisée; Dans cette méthode, je viens de mettre à jour le cadre de chaque sous-couche afin qu'il corresponde aux limites actuelles du calque de ma sous-vue.

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

Selon this answer, layoutSubviews n'est pas appelé dans tous les cas nécessaires. J'ai trouvé cette méthode de délégué plus efficace:

- (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;
}
3
pckill

Ma solution lorsque je crée avec une bordure en pointillé

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

Solution KVO Swift 3.x (Mise à jour de la réponse de @ arango_86)

Ajouter un observateur

self.addObserver(
    self, 
    forKeyPath: "<YOUR_VIEW>.bounds", 
    options: .new, 
    context: nil
)

Observez les valeurs

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