调整动画大小后UIButton不尊重Aspect Fill contentMode
Posted
技术标签:
【中文标题】调整动画大小后UIButton不尊重Aspect Fill contentMode【英文标题】:UIButton not respect Aspect Fill contentMode after resizing animation 【发布时间】:2014-10-08 17:49:23 【问题描述】:我正在使用自动布局。以下是视图的初始状态。
中间是一个包含在视图中的按钮。按钮有contentMode Aspect Fill,图片设置为按钮的背景图。
然后我用下面的代码对视图进行变换,将中心卡片放大以填满屏幕,并将图像移动到视图的顶部:
cardTrailingSpaceConstraint.constant = 0
cardLeadingSpaceConstraint.constant = 0
cardView.removeConstraint(cardAspectRatioConstraint)
let cardHeightConstraint = NSLayoutConstraint(item: cardView, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 1.0, constant: 0)
view.addConstraint(cardHeightConstraint)
dishImageButton.removeConstraint(dishButtonBottomSpaceConstraint)
let dishButtonHeightConstraint = NSLayoutConstraint(item: dishImageButton, attribute: .Height, relatedBy: .Equal, toItem: cardView, attribute: .Height, multiplier: 0.2, constant: 0)
cardView.addConstraint(dishButtonHeightConstraint)
cardView.setNeedsUpdateConstraints()
UIView.animateWithDuration(0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, options: nil, animations: [unowned self] () -> Void in
self.cardHeader.alpha = 0
self.cardView.layer.cornerRadius = 0
self.cardView.layoutIfNeeded()
) [unowned self] (finished) -> Void in
结果是:
然而,这不是我想要的。该按钮不尊重 contentMode,然后图像被拉伸。
谁能告诉我如何维护按钮的Aspect Fill contentMode?
【问题讨论】:
【参考方案1】:-
将按钮类型设置为
UIButtonTypeCustom
(故事板或 xib 中的“自定义”)。
设置按钮的图像,而不是按钮的背景图像。
在viewDidLoad
中,将button.imageView.contentMode
设置为UIViewContentMode.ScaleAspectFill
。
【讨论】:
为我工作。请记住在 #3 上将其绑定到 IBOutlet 以获得正确的按钮。 这很好用,但现在我遇到了约束问题。如何将约束目标设置为图像按钮,而不是背景按钮图像? 在 Swift 5.2 上工作。我的问题是我设置的是背景图像而不是图像。谢谢!【参考方案2】:斯威夫特 3
脱离 Rob 的回答:
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 80, height: 30))
btn.setImage(UIImage(named: "albumsBtn"), for: UIControlState.normal)
btn.imageView?.contentMode = UIViewContentMode.scaleAspectFit
btn.addTarget(self.navigationController, action: #selector(CustomGalleryViewController.showAlbums(_:)), for: UIControlEvents.touchUpInside)
let item = UIBarButtonItem(customView: btn)
self.navigationItem.leftBarButtonItem = item
【讨论】:
【参考方案3】:在 Xcode 10.1 中,您可以使用界面生成器。在右侧的属性检查器中,使用 Control 部分,如下所示:
【讨论】:
【参考方案4】:在[btn setImage:forState:]用法之前试试这个:
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
btn.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
斯威夫特 4
//Center
btn.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.center
//Left
btn.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left
//Right
btn.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
【讨论】:
【参考方案5】:Swift 2.x 版本:
let myButton = UIButton(type: .Custom)
myButton.frame = CGRectMake(0, 0, 200, 20)
myButton.backgroundColor = UIColor.blackColor()
myButton.imageView.contentMode = .ScaleAspectFill // ALTERNATIVE: .ScaleAspectFit
myButton.setImage(UIImage(named: "myImageName"), forState: .Normal)
myButton.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
view.addSubview(myButton)
【讨论】:
绝对!对我来说,直到我制作了自定义类型,它才起作用。谢谢。【参考方案6】:斯威夫特 2
button.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
所有内容模式:
.ScaleToFill
.ScaleAspectFit
.ScaleAspectFill
.Redraw
.Center
.Top
.Bottom
.Left
.Right
.TopLeft
.TopRight
.BottomLeft
.BottomRight
【讨论】:
【参考方案7】:斯威夫特 4.2
扩展
// Inspectable image content mode
extension UIButton
/// 0 => .ScaleToFill
/// 1 => .ScaleAspectFit
/// 2 => .ScaleAspectFill
@IBInspectable
var imageContentMode: Int
get
return self.imageView?.contentMode.rawValue ?? 0
set
if let mode = UIViewContentMode(rawValue: newValue),
self.imageView != nil
self.imageView?.contentMode = mode
更新:这个和其他答案在 ios 11 中对我不起作用。最接近的答案是 @Jaro 但我认为最好制作一个 UIImageView 并在它上面添加一个按钮,或者创建一个自定义的 UIImageView 类,它有一个手势识别器和点击动画。
【讨论】:
您应该在扩展行中添加 @IBDesignable 以使其在界面生成器中工作 SWIFT 4.2 extension UIButton /// 0 => .ScaleToFill /// 1 => .ScaleAspectFit /// 2 => .ScaleAspectFill @IBInspectable var imageContentMode: Int get return self.imageView ?.contentMode.rawValue ?? 0 设置 if let mode = UIView.ContentMode(rawValue: newValue), self.imageView != nil self.imageView?.contentMode = mode 【参考方案8】:语言似乎有更新。
我不得不深入挖掘以获得 xscoder 解决方案:
myButton.imageView.contentMode = .ScaleAspectFill
更新版本如下:
myButton.imageView?.contentMode = UIView.ContentMode.scaleAspectFit
【讨论】:
【参考方案9】:斯威夫特
对于按钮有 contentMode Aspect Fill:
btn.contentHorizontalAlignment = .fill
btn.contentVerticalAlignment = .fill
btn.imageView?.contentMode = .scaleAspectFill
【讨论】:
【参考方案10】:Swift 5.0
用于自定义 UIButton
和 .scaleAspectFill
的代码
var mainImageButton : UIButton =
var imageButton = UIButton()
imageButton.translatesAutoresizingMaskIntoConstraints = false
imageButton.contentMode = .scaleAspectFit
imageButton.backgroundColor = .white
imageButton.layer.cornerRadius = 80 / 2
// The short way
imageButton.contentMode = .scaleAspectFit
// The long way
imageButton.imageView?.contentMode = UIView.ContentMode.scaleAspectFill
imageButton.clipsToBounds = true
return imageButton
()
【讨论】:
【参考方案11】:可能会帮助某人
button.subviews.first?.contentMode = .scaleAspectFit
【讨论】:
【参考方案12】:您可以对按钮进行子类化并添加以下内容:
class FitButton: UIButton
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
override func layoutSubviews()
self.imageView?.contentMode = .scaleAspectFill
self.contentHorizontalAlignment = .fill
self.contentVerticalAlignment = .fill
super.layoutSubviews()
【讨论】:
【参考方案13】:当我为 BarButtonItem 使用自定义按钮时,此解决方案对我有用 1. 从服务器加载图片 2. 裁剪图像 3. 设置按钮图片 这是裁剪图像的功能:
extension UIImage
func crop(to:CGSize) -> UIImage
guard let cgimage = self.cgImage else return self
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
else if to.width < to.height //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
else //Square
if contextSize.width >= contextSize.height //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
else //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
let rect: CGRect = CGRect(x : posX, y : posY, width : cropWidth, height : cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
cropped.draw(in: CGRect(x : 0, y : 0, width : to.width, height : to.height))
return cropped
【讨论】:
以上是关于调整动画大小后UIButton不尊重Aspect Fill contentMode的主要内容,如果未能解决你的问题,请参考以下文章