UIButton not respect Aspect Fill contentMode after

2019-02-04 11:43发布

问题:

I am use auto layout. Following is the initial state of the view.

In the centre is a button contained in a view. The button has contentMode Aspect Fill, and the image is set as the background image of the button.

Then I use the following code to transform the view, which will enlarge the centre card to fill the screen, and move the image to the top of the view:

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

        }

The result is:

However, it is not what I want. The button is not respecting the contentMode and the image then get stretched.

Can anyone tell me how to maintain the Aspect Fill contentMode of the button?

回答1:

  1. Set the button type to UIButtonTypeCustom (“Custom” in a storyboard or xib).
  2. Set the button's image, not the button's background image.
  3. In viewDidLoad, set button.imageView.contentMode to UIViewContentMode.ScaleAspectFill.


回答2:

Swift 3


Going off of Rob's answer:

    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:

Swift 2

button.imageView?.contentMode = UIViewContentMode.ScaleAspectFit

all contentMode:

  .ScaleToFill
   .ScaleAspectFit
   .ScaleAspectFill
   .Redraw 
   .Center 
   .Top
   .Bottom
   .Left
   .Right
   .TopLeft
   .TopRight
   .BottomLeft
   .BottomRight


回答4:

Swift 2.x version:

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)


回答5:

Swift 4.2

Extension

// 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
            }
        }
    }
}

UPDATE: This and other answers doesn't work for me in ios 11. The most closest answer is by @Jaro but i think it's better to make an UIImageView and over it add a button, or create a custom class of UIImageView that would have a gesture recognizer and click animation.



回答6:

Try this before [btn setImage:forState:] usage:

btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
btn.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;


回答7:

might help someone

button.subviews.first?.contentMode = .scaleAspectFit


回答8:

You can subclass the button and add these:

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()


    }

}


回答9:

In Xcode 10.1 you can use interface builder. In the attributes inspector on the right hand side, use the Control section as follows:



回答10:

The language seems to have had an update.

I had to dig a little deeper to get xscoder solution for:

myButton.imageView.contentMode = .ScaleAspectFill 

the updated version is as follows:

myButton.imageView?.contentMode = UIView.ContentMode.scaleAspectFit



标签: ios swift ios8