iOS10中UIBarButtonItem设置UIEdgeInsets致图片压缩问题排查
这个问题我之前也踩过坑,本质是iOS10和iOS11+在UIBarButtonItem处理imageInsets的布局逻辑上存在差异。
问题原因
在iOS10及更早版本中,当你通过init(image:style:target:action:)初始化UIBarButtonItem后直接设置imageInsets,系统不会根据Insets的数值自动调整按钮的整体尺寸。它会试图把带Insets的图片强行塞进基于原始图片尺寸计算出来的按钮框架里,这就导致了图片被压缩变形。而iOS11之后苹果重构了导航栏的布局系统,加入了自适应逻辑,会自动根据图片和Insets调整按钮大小,所以不会出现这个问题。
修复方案
最可靠的解决办法是用自定义UIButton作为UIBarButtonItem的customView,这样你可以完全控制图片的布局,不受系统旧逻辑的限制。修改你的便利初始化器如下:
convenience init(type: ButtonType, target: Any?, selector: Selector) { // 创建自定义UIButton let customButton = UIButton(type: .custom) let buttonImage = type.image.withRenderingMode(.alwaysTemplate) // 设置按钮图片及Insets customButton.setImage(buttonImage, for: .normal) customButton.imageEdgeInsets = type.imageInsets // 添加点击事件 customButton.addTarget(target, action: selector, for: .touchUpInside) // 根据图片尺寸和Insets计算按钮的合适大小,避免压缩 let buttonWidth = buttonImage.size.width + abs(type.imageInsets.left) + abs(type.imageInsets.right) let buttonHeight = buttonImage.size.height + abs(type.imageInsets.top) + abs(type.imageInsets.bottom) customButton.frame = CGRect(x: 0, y: 0, width: buttonWidth, height: buttonHeight) // 用customView初始化UIBarButtonItem self.init(customView: customButton) }
如果你不想改用customView,也可以尝试手动设置UIBarButtonItem的width属性来强制指定按钮尺寸,不过这种方法在某些场景下可能不如customView稳定:
convenience init(type: ButtonType, target: Any?, selector: Selector) { let image: UIImage = type.image.withRenderingMode(.alwaysTemplate) self.init(image: image, style: .plain, target: target, action: selector) imageInsets = type.imageInsets // 根据图片和Insets计算所需宽度,强制设置给UIBarButtonItem let requiredWidth = image.size.width + abs(imageInsets.left) + abs(imageInsets.right) self.width = requiredWidth }
补充说明
用customView的方式不仅能解决iOS10的压缩问题,还能让你对按钮的样式、点击反馈等有更灵活的控制,推荐优先使用这种方案。
内容的提问来源于stack exchange,提问作者Kex
相关产品推荐
相关产品推荐

