iOS:frame.size.width / 2不会在每个设备上产生一个圆

我知道公式frame.size.width/2应该产生一个圆形边框,但是在XCode中,我目前正在经历一些差异。

我有两个testing设备(iPhone6和第五代iPod touch)我也有模拟器运行。 我的设备都能正确显示,但模拟器将我的圆圈绘制成圆angular矩形:

在这里输入图像说明

我用来实现这个(虽然很简单)的代码是:

 imgAvatar.layer.masksToBounds = true imgAvatar.clipsToBounds = true imgAvatar.layer.cornerRadius = imgAvatar.frame.size.width/2 imgAvatar.layer.borderWidth = 5 imgAvatar.layer.borderColor = UIColor.whiteColor().CGColor 

这有什么道理吗? 这让我疯狂!

更新为了清除混淆, UIImageView在我的故事板中声明为190x190它也有一个1:1宽高比约束应用于它,以确保它保持成比例的宽度和高度。

更新2为了把任何怀疑关于我的自动布局约束睡觉,我已附加下面的图像显示为imgAvatar设置的约束。 正如您所看到的宽度和高度匹配,AR设置为确保它保持1:1的比例。 我希望能够清除任何进一步的疑虑

在这里输入图像说明

答案 Leonardo指出了一个非常实用和可重用的解决scheme来解决这个问题,使用Swift扩展可以确保给定的UIImage总是正方形的,因此总是产生一个圆圈,我已经在下面贴出了Leonardo的解决scheme:

 extension UIImage { var circleMask: UIImage { let square = size.width < size.height ? CGSize(width: size.width, height: size.width) : CGSize(width: size.height, height: size.height) let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square)) imageView.contentMode = UIViewContentMode.ScaleAspectFill imageView.image = self imageView.layer.cornerRadius = square.width/2 imageView.layer.borderColor = UIColor.whiteColor().CGColor imageView.layer.borderWidth = 5 imageView.layer.masksToBounds = true UIGraphicsBeginImageContext(imageView.bounds.size) imageView.layer.renderInContext(UIGraphicsGetCurrentContext()) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } } imgAvatar.image = yourImage.circleMask 

您可以创build一个扩展名,将遮罩和边框直接应用于图像,因此无论屏幕大小/比例如何都将始终如一:

 extension UIImage { var circleMask: UIImage { let square = CGSize(width: min(size.width, size.height), height: min(size.width, size.height)) let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square)) imageView.contentMode = UIViewContentMode.ScaleAspectFill imageView.image = self imageView.layer.cornerRadius = square.width/2 imageView.layer.borderColor = UIColor.whiteColor().CGColor imageView.layer.borderWidth = 5 imageView.layer.masksToBounds = true UIGraphicsBeginImageContext(imageView.bounds.size) imageView.layer.renderInContext(UIGraphicsGetCurrentContext()) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } } imgAvatar.image = yourImage.circleMask 

那么,Autolayout应该是问题。 可以看出, 右侧imgAvatar的高度大于 左侧imgAvatar的高度。

imgAvatar右侧的大小为190 x 190 ,左侧的大小为200 x 200 ,但在左侧,您设置的angular落半径是190/2,95px,而应该是100px

如果您不希望imgAvatar以1:1resize,请在imgAvatar的 nib文件中设置“ 高度宽度约束”。

  1. 在你的笔尖selectimgAvatar。
  2. 编辑器> Pin>高度
  3. 在你的笔尖selectimgAvatar。
  4. 编辑器>引脚>宽度

要么

尝试移动你的代码到viewDidLayoutSubviews

要么

子类化你的UIImageView并在其awakeFromNib方法中设置其angular半径

请让我们知道,如果它的工作。 谢谢!

如果你在iOS8.3中testing,你应该在UI对象上调用layoutIfNeed来获取它的框架。 请阅读iOS8.3发行说明

例如:

 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; // code that sets up the button, but doesn't yet add it to a window CGRect titleFrame = button.titleLabel.frame; // code that relies on the correct value for titleFrame 

你现在需要:

 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; // code that sets up the button, but doesn't yet add it to a window [button layoutIfNeeded]; // This is also safe pre-iOS 8.3 CGRect titleFrame = button.titleLabel.frame; // code that relies on the correct value for titleFrame 

据说对于UIButton和子类,你也可以用你的UI对象来尝试。

在与iOS 8.3进行链接时,任何依赖UIButton子视图的布局信息(如框架)的代码在button不在窗口层次结构中时,都需要将layoutIfNeeded发送到button,然后才能获取布局信息(如button.titleLabel .frame)来确保布局值是最新的。

此外,由于imgAvatar的cornerRadius被设置为imgFrame的大小的1/2,所以只有当该angular的Radius值= imgAvatar的宽度(和高度)的1/2时才会得到一个圆。

所以,电话后:

 imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2 

validation:

  • imgAvatar的帧大小及其cornerRadius
  • 确保图像平方

问题是,当应用圆时,视图边界仍然被认为是默认的(320×480) ,所以如果你已经设置了与屏幕相关的约束,例如iPhone 6/6 +上的图像会更大。

有各种解决scheme,但如果你想要一个快速的,只需把你的代码:

 imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2 

在视图控制器中的- viewDidLayoutSubviews或在视图中的- layoutSubviews中, 检查cornerRadius是否与图像的帧宽度/ 2不同 。 像这样的东西:

 if (imgAvatar.layer.cornerRadius != imgFrame.frame.size.width/2) { imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2 } 

您使用的公式只适用于平方图像。 你使用自动布局? 也许它可能会延伸到您使用的设备。 如果是这种情况,则高度将高于宽度,反之亦然。 也就是说,图像将是某种矩形,不会产生完美的圆形。