UIImageView 上的一致性居中 CALayer 子层 [英] Consistenlty Centering CALayer Sublayer over a UIImageView

查看:25
本文介绍了UIImageView 上的一致性居中 CALayer 子层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • Xcode 7.2
  • 斯威夫特 2

我的问题是我无法始终将 CALayer 居中.

我有一个相关的 SO 问题

这是我的 print() 纵向模式旋转输出:

willTransitionToTraitCollection()!blurFilerMask != nilresetMaskOverlay()!(160.0, 128.0)328.0200.0BlurFilterMask ->drawInContext()!

但是 CALayer 在横向模式下居中:

这是我的 print() 横向模式旋转输出:

willTransitionToTraitCollection()!blurFilerMask != nilresetMaskOverlay()!(284.0, 108.0)568.0200.0BlurFilterMask ->drawInContext()!

我的 UIImage Size Inspector Screenshot,Constraints 最需要考虑的部分:

我的 UIImage 模式是 Scale To Fill

这是我的TestViewController中的所有代码:

导入 UIKit类 TestViewController: UIViewController {@IBOutlet 弱 var heroImageView:UIImageView!var blurFilterMask:BlurFilterMask!= 零覆盖 func viewDidLoad() {super.viewDidLoad()//加载视图后进行任何其他设置.}覆盖 func viewDidLayoutSubviews() {super.viewWillLayoutSubviews()resetMaskOverlay()}覆盖 func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {super.willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator)打印(willTransitionToTraitCollection()!")如果 blurFilterMask != nil {打印(blurFilerMask != nil")blurFilterMask.removeFromSuperlayer()blurFilterMask = nil}}func resetMaskOverlay(){打印(resetMaskOverlay()!")打印(heroImageView.center)打印(CGRectGetWidth(heroImageView.bounds))打印(CGRectGetHeight(heroImageView.bounds))如果 blurFilterMask == nil {blurFilterMask = BlurFilterMask()}blurFilterMask.diameter = 80blurFilterMask.frame = heroImageView.boundsblurFilterMask.origin = heroImageView.centerblurFilterMask.shouldRasterize = trueheroImageView.layer.addSublayer(blurFilterMask)blurFilterMask.setNeedsDisplay()}}

这是我的 CALayer,我称之为 BlurFilterMask:

导入 UIKit类 BlurFilterMask : CALayer {私人让 GRADIENT_WIDTH : CGFloat = 50.0变量原点:CGPoint = CGPointZero {已设置{//setNeedsDisplay()}}变量直径:CGFloat = 50.0 {已设置{//setNeedsDisplay()}}覆盖初始化(){超级初始化()}需要初始化?(编码器aDecoder:NSCoder){fatalError("init(coder:) 尚未实现")}覆盖 func drawInContext(ctx: CGContext) {print("BlurFilterMask -> drawInContext()!")CGContextSaveGState(ctx)让 clearRegionRadius : CGFloat = self.diameter * 0.5让 blurRegionRadius : CGFloat = clearRegionRadius + GRADIENT_WIDTH让 baseColorSpace = CGColorSpaceCreateDeviceRGB();let colours : [CGFloat] = [0.0, 0.0, 0.0, 0.0,//清除区域0.0, 0.0, 0.0, 0.6]//模糊区域颜色让 colourLocations : [CGFloat] = [0.0, 0.0]让梯度 = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2)CGContextDrawRadialGradient(ctx,渐变,self.origin,clearRegionRadius,self.origin,blurRegionRadius,.DrawsAfterEndLocation);}}

现在进一步测试这个问题,我可以证明与我的第一个屏幕截图完全相反(第一个场景是:纵向模式未居中,而横向模式正确居中).

在下一个例子中.我已经更改了 UIImageView 约束,以便填充 UIImageView 填充 SuperView,您可以在下面看到我的 CALayer 在纵向模式下正确居中,但不是横向模式,这与我之前的屏幕截图演示完全相反:

UIImageView 约束:

带有 UIImageView填充"超视图约束的纵向模式:

具有 UIImageView填充"超视图约束的横向模式:

解决方案

您的代码的问题是设置 BlurFilterMask 的中心.中心应该是 BlurFilterMask 的中心吧?使用这个更新的resetMaskOverlay"函数.

 func resetMaskOverlay(){打印(resetMaskOverlay()!")打印(heroImageView.center)打印(CGRectGetWidth(heroImageView.bounds))打印(CGRectGetHeight(heroImageView.bounds))如果 blurFilterMask == nil {blurFilterMask = BlurFilterMask()}blurFilterMask.diameter = 80blurFilterMask.frame = heroImageView.boundsblurFilterMask.origin = CGPointMake(CGRectGetMidX(heroImageView.bounds), CGRectGetMidY(heroImageView.bounds))blurFilterMask.shouldRasterize = trueheroImageView.layer.addSublayer(blurFilterMask)blurFilterMask.setNeedsDisplay()}

  • Xcode 7.2
  • Swift 2

My issue is that I cannot consistently center my CALayer.

I have a related SO question here. The answer to this question was forward progress and brings me to the issue I am having now. Note in the answer to my related question, @WarrenBurton seems to only test portrait mode.

I think this issue, which really is calculating/positioning a sublayer dead center over a UIImageView may relate to the actual size of the Image selected for the UIImageView but I could be wrong about this.

Here is my print() output for portrait mode rotation:

willTransitionToTraitCollection()!
blurFilerMask != nil
resetMaskOverlay()!
(160.0, 128.0)
328.0
200.0
BlurFilterMask -> drawInContext()!

But the CALayer is centered in Landscape mode:

Here is my print() output for landscape mode rotation:

willTransitionToTraitCollection()!
blurFilerMask != nil
resetMaskOverlay()!
(284.0, 108.0)
568.0
200.0
BlurFilterMask -> drawInContext()!

My UIImage Size Inspector Screenshot, Constraints most important part to consider perhaps:

My UIImage mode is Scale To Fill

Here is all the code in my TestViewController:

import UIKit

class TestViewController: UIViewController {

    @IBOutlet weak var heroImageView: UIImageView!
      var blurFilterMask:BlurFilterMask! = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func viewDidLayoutSubviews() {
        super.viewWillLayoutSubviews()
        resetMaskOverlay()
    }


    override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator)
        print("willTransitionToTraitCollection()!")

        if blurFilterMask != nil {
            print("blurFilerMask != nil")
            blurFilterMask.removeFromSuperlayer()
            blurFilterMask = nil
        }

    }

    func resetMaskOverlay(){
        print("resetMaskOverlay()!")

        print(heroImageView.center)
        print(CGRectGetWidth(heroImageView.bounds))
        print(CGRectGetHeight(heroImageView.bounds))

        if blurFilterMask == nil {
            blurFilterMask = BlurFilterMask()
        }

        blurFilterMask.diameter = 80
        blurFilterMask.frame = heroImageView.bounds
        blurFilterMask.origin = heroImageView.center
        blurFilterMask.shouldRasterize = true
        heroImageView.layer.addSublayer(blurFilterMask)
        blurFilterMask.setNeedsDisplay()

    }

}

Here is my CALayer which I call BlurFilterMask:

import UIKit

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) {
        print("BlurFilterMask -> drawInContext()!")
        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);


    }

}

Now further testing of this issue, I can demonstrate the exact opposite of my first screenshots (the first scenario was: Portrait mode is NOT centered and Landscape mode is correctly centered).

In this next example. I have changed the UIImageView constraints so that fill the UIImageView fills the SuperView and you can see below my CALayer is correctly centered in Portrait mode but NOT Landscape mode, the exact opposite of my previous screenshot demo:

UIImageView Constraints:

Portrait mode with UIImageView "fill" superview constraints:

Landscape mode with UIImageView "fill" superview constraints:

解决方案

Problem with your code is setting centre of your BlurFilterMask. Centre should centre of BlurFilterMask right? Use this updated 'resetMaskOverlay' function.

    func resetMaskOverlay(){
    print("resetMaskOverlay()!")

    print(heroImageView.center)
    print(CGRectGetWidth(heroImageView.bounds))
    print(CGRectGetHeight(heroImageView.bounds))

    if blurFilterMask == nil {
        blurFilterMask = BlurFilterMask()
    }

    blurFilterMask.diameter = 80
    blurFilterMask.frame = heroImageView.bounds
    blurFilterMask.origin = CGPointMake(CGRectGetMidX(heroImageView.bounds), CGRectGetMidY(heroImageView.bounds))
    blurFilterMask.shouldRasterize = true
    heroImageView.layer.addSublayer(blurFilterMask)
    blurFilterMask.setNeedsDisplay()

}

这篇关于UIImageView 上的一致性居中 CALayer 子层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆