在 UIImageView 上一致地居中 CALayer 子层

Posted

技术标签:

【中文标题】在 UIImageView 上一致地居中 CALayer 子层【英文标题】:Consistenlty Centering CALayer Sublayer over a UIImageView 【发布时间】:2016-02-28 01:33:43 【问题描述】: Xcode 7.2 斯威夫特 2

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

我有一个相关的 SO 问题 here。这个问题的答案是向前进步,并把我带到了我现在遇到的问题上。请注意,在我的相关问题的答案中,@WarrenBurton 似乎只测试纵向模式。

我认为这个问题实际上是在 UIImageView 上计算/定位子层死点,这可能与为 UIImageView 选择的图像的实际大小有关,但我可能对此有误。

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

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

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

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

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

我的 UIImage Size Inspector Screenshot,约束最重要的部分可能要考虑:

我的 UIImage 模式是Scale To Fill

这是我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()

    


这是我的 CALayer,我称之为 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);


    


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

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

UIImageView 约束:

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

带有 UIImageView“填充”超级视图约束的横向模式:

【问题讨论】:

【参考方案1】:

您的代码的问题是设置 BlurFilterMask 的中心。中心应该是 BlurFilterMask 的中心吗?使用此更新的“resetMaskOverlay”功能。

    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 子层的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIButton 中将 UIImageView 与它的文本居中?

带有 snapkit 的垂直居中 UIImageView

调整大小后使用自动布局以编程方式居中 UIImageVIew

为啥这个 UIImageView 会自动居中?

UIImageView 高度与 UILabel 字体高度相同。在 UIStackView 内居中

以编程方式使用约束使 UIIMageView 居中