2016-02-15 13 views
6
  • Xcode 7.2
  • Swift 2

Ich versuche, mit einem Bild zu überlagern, was ich einen "BlurFilterMask" nenne. Es ist ein CALayer, dass ich mit Swift-Code dynamisch hinzufügen, hier ist die BlurFilterMask:eine CALayer Unterschicht hinzufügen über UIImageView zentriert

class BlurFilterMask : CALayer { 

    private let GRADIENT_WIDTH : CGFloat = 50.0 

    var origin : CGPoint = CGPointZero { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    var diameter : CGFloat = 50.0 { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    override init() { 
     super.init() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override func drawInContext(ctx: CGContext) { 
     CGContextSaveGState(ctx) 

     let clearRegionRadius : CGFloat = self.diameter * 0.5 
     let blurRegionRadius : CGFloat = clearRegionRadius + GRADIENT_WIDTH 

     let baseColorSpace = CGColorSpaceCreateDeviceRGB(); 
     let colours : [CGFloat] = [0.0, 0.0, 0.0, 0.0,  // Clear region 
     0.0, 0.0, 0.0, 0.6] // blur region color 
     let colourLocations : [CGFloat] = [0.0, 0.0] 
     let gradient = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2) 


     CGContextDrawRadialGradient(ctx, gradient, self.origin, clearRegionRadius, self.origin, blurRegionRadius, .DrawsAfterEndLocation); 

    } 

} 

In meinem UIViewController.viewDidLoad() Ich nenne addMaskOverlay() und hier ist die Umsetzung:

func addMaskOverlay(){ 
     let blurFilterMask = BlurFilterMask() 

     blurFilterMask.diameter = 80 
     blurFilterMask.frame = heroImageView.bounds 
     blurFilterMask.origin = heroImageView.center 
     blurFilterMask.shouldRasterize = true 

     heroImageView.layer.addSublayer(blurFilterMask) 

     blurFilterMask.setNeedsDisplay() 
    } 

Egal was Simulator I zulaufen, sei es iPhone 5 oder iPhone 6 oder iPad 2, für Beispiele, habe ich immer die gleiche Mitte, Breite und Höhe:

  • print (heroImageView.center) = (300,0, 67,5)
  • 012.351.
  • print (CGRectGetWidth (heroImageView.bounds)) = 600,0
  • print (CGRectGetHeight (heroImageView.bounds)) //135.0

Aber das Zentrum meines BlurFilterMask ist immer irgendwo anders auf dem Gerätesimulator in Abhängigkeit und es beginnt nie im Zentrum von UIImageView, zB in iPhone 5:

enter image description here

und hier ist das iPhone 6:

enter image description here

Ich dachte, vielleicht brauche ich vertikal zentriert und horizontal Einschränkungen für meine CALayer BlurFilterMask Zentrierung so habe ich versucht, das Hinzufügen Einschränkungen:

heroImageView.layer.addSublayer(blurFilterMask) 

let xConstraint = NSLayoutConstraint(item: blurFilterMask, attribute: .CenterX, relatedBy: .Equal, toItem: heroImageView, attribute: .CenterX, multiplier: 1, constant: 0) 

let yConstraint = NSLayoutConstraint(item: blurFilterMask, attribute: .CenterY, relatedBy: .Equal, toItem: heroImageView, attribute: .CenterY, multiplier: 1, constant: 0) 

heroImageView.addConstraint(xConstraint) 
heroImageView.addConstraint(yConstraint) 

Aber ich kann nicht Constraints summieren sich zu einem CALayer Ich glaube nicht, ich bekomme ein Fehler, wenn ich versuche:

beenden app aufgrund nicht abgefangene Ausnahme 'NSInvalidArgumentException', Grund: ‚* + [NSLayoutConstraint constraintWithItem: Attribut: relatedBy: toItem: Attribut: Dimension: konstante:]: Constraint Elemente jeder muss ein Instanz UIView oder NSLayoutGuide. '**

Es scheint, wie die Frage könnte Einschränkungen sein, aber wenn ich nicht Zwänge zu einer CALayer hinzufügen ...

Dieser Code hat nicht geholfen ...

Ich bin mir nicht sicher, wohin ich von hier gehe, alle Vorschläge wären sehr willkommen.

+0

Haben Sie versucht, Ihre Messungen zu tun, basierend auf dem Gerät 'UIScreen.mainScreen(). Bounds'? –

+0

Verwenden Sie die Subtraktion von den UIScreen.mainScreen.bounds und den my UIImageView.bounds, um das Zentrum von UIImageView zu finden? –

+0

Wenn Sie sagen, verwenden Sie einfach die UIScreen.mainScreen.bounds, die meine BlurFilterMask über die gesamte angezeigte Ansicht zentrieren würden, und das ist nicht das, was ich versuche zu erreichen. –

Antwort

3

Das Problem ist, dass, wenn viewDidLoad aufgerufen wird das Layout noch nicht getan wurde, so dass Ihre Messungen aus dem Ausgangszustand des View-Controllers genommen werden, am ehesten von der Storyboard-Größe, wenn das ist, was Sie verwenden.

Sie müssen blurFilterMask aufrufen, sobald das Layout abgeschlossen ist und die endgültige Größe heroImageView bekannt ist.

Sie können dies durch Überschreiben viewDidLayoutSubviews, die ...

Wird aufgerufen, um den View-Controller zu benachrichtigen, dass seine Ansicht gerade seine Unteransichten angelegt hat.

lesen the docs, da es einige Bedingungen, aber in Ihrem Fall das tut Arbeit, die Sie mit diesem zu verlassen ..

class ViewController: UIViewController { 

    @IBOutlet var heroImageView: UIImageView! 

    var blurFilterMask:BlurFilterMask! = nil 

    func resetMaskOverlay(){ 

     if blurFilterMask == nil { 

      blurFilterMask = BlurFilterMask() 

      blurFilterMask.diameter = 120 

      heroImageView.layer.addSublayer(blurFilterMask) 

     } 

     blurFilterMask.frame = heroImageView.bounds 
     blurFilterMask.origin = heroImageView.center 

    } 


    override func viewDidLayoutSubviews() { 
     resetMaskOverlay() 
    } 

} 

nahm ich diese Zeile in BlurFilterMask

CGContextTranslateCTM(ctx, 0.0, yDiff)*/ 

eigentlich sein sollte auskommentiert, da es nicht viel Sinn machte, wenn ...

class BlurFilterMask : CALayer { 

    let GRADIENT_WIDTH : CGFloat = 50.0 

    var origin : CGPoint = CGPointZero { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 
    var diameter : CGFloat = 50.0 { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    override func drawInContext(ctx: CGContext) { 
     CGContextSaveGState(ctx) 

     let clearRegionRadius : CGFloat = self.diameter * 0.5 
     let blurRegionRadius : CGFloat = clearRegionRadius + GRADIENT_WIDTH 

     let baseColorSpace = CGColorSpaceCreateDeviceRGB(); 
     let colours : [CGFloat] = [0.0, 0.0, 0.0, 0.0,  // Clear region 
      0.0, 0.0, 0.0, 0.6] // blur region color 
     let colourLocations : [CGFloat] = [0.0, 0.0] 
     let gradient = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2) 


     CGContextDrawRadialGradient(ctx, gradient, self.origin, clearRegionRadius, self.origin, blurRegionRadius, .DrawsAfterEndLocation); 

    } 

} 

test1-5stest1-6s+

+0

Ich habe das Gefühl, dass Sie richtig sind, aber ich werde nicht in der Lage sein, bis spät in die Nacht zu sehen, updaten Sie bald, danke –

+0

Hoppla, ja, mein üblicher Fehler. Du brauchst einen einmaligen Mech, um das zu verhindern. Siehe Bearbeiten - Ich habe die Ebene als Ivar hinzugefügt, um sie zu verfolgen. –

+0

Seltsam. Der genaue Code funktioniert für rotiert auf meinen Sims, es ist ein bisschen flickerig aber nichts, das nicht mit etwas Alpha gelöst werden könnte. Alternativ können Sie die Ebene beibehalten und ihren Ursprung zurücksetzen. –

Verwandte Themen