调整动画大小后,UIButton不尊重Aspect Fill contentMode

时间:2014-10-08 17:49:24

标签: ios swift ios8

我使用自动布局。以下是视图的初始状态。

中间是视图中包含的按钮。该按钮具有contentMode Aspect Fill,图像被设置为按钮的背景图像。

enter image description here

然后我使用以下代码转换视图,这将放大中心卡以填充屏幕,并将图像移动到视图的顶部:

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

        }

结果是:

enter image description here

然而,这不是我想要的。该按钮不符合contentMode,然后图像被拉伸。

有谁能告诉我如何维护按钮的Aspect Fill contentMode?

13 个答案:

答案 0 :(得分:41)

  1. 将按钮类型设置为UIButtonTypeCustom(故事板或xib中的“自定义”)。
  2. 设置按钮的图像,而不是按钮的背景图像。
  3. viewDidLoad中,将button.imageView.contentMode设为UIViewContentMode.ScaleAspectFill

答案 1 :(得分:12)

Swift 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

答案 2 :(得分:6)

Swift 2

button.imageView?.contentMode = UIViewContentMode.ScaleAspectFit

所有contentMode:

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

答案 3 :(得分: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)

答案 4 :(得分:5)

Swift 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,它将具有手势识别器和点击动画。

答案 5 :(得分:5)

[btn setImage:forState:] 用法之前尝试此操作:

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

答案 6 :(得分:3)

if(!empty($_SESSION["cart_item"])) { $dirty = false; foreach($_SESSION["cart_item"] as $k => $v) { if($produto === $_SESSION["cart_item"][$k]['id']) { $dirty = true if(empty($_SESSION["cart_item"][$k]["quantidade"])) { $_SESSION["cart_item"][$k]["quantidade"] = 1; } $_SESSION["cart_item"][$k]["quantidade"] += 1; } } if(!$dirty) { // the id was not present in the array // we need to add it. $_SESSION["cart_item"][] = [...]; } } else { $_SESSION["cart_item"] = $itemArray; } 代码用于带有Swift 5.0的自定义UIButton

.scaleAspectFill

答案 7 :(得分:2)

您可以将按钮子类化并添加以下内容:

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


    }

}

答案 8 :(得分:2)

在Xcode 10.1中,您可以使用界面生成器。在右侧的属性检查器中,使用“控制”部分,如下所示:

ios swift xcode 10.1 uibutton scale to fill

答案 9 :(得分:2)

该语言似乎已有更新。

我不得不更深入地研究xscoder解决方案:

import React from "react";
import ReactDOM from "react-dom";
import { NavLink, BrowserRouter } from "react-router-dom";
import { withStyles } from "@material-ui/core/styles";

const styles = {
  btn: {},
  active: {
    "& $btn": {
      backgroundColor: "#2A354F",
      color: "#fff"
    }
  }
};
function App(props) {
  return (
    <BrowserRouter>
      <div className="App">
        <NavLink to="/" activeClassName={props.classes.active}>
          <button className={props.classes.btn}>Link</button>
        </NavLink>
      </div>
    </BrowserRouter>
  );
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);

更新的版本如下:

myButton.imageView.contentMode = .ScaleAspectFill

答案 10 :(得分:1)

可能会帮助某人

button.subviews.first?.contentMode = .scaleAspectFit

答案 11 :(得分:0)

快速

用于按钮具有contentMode纵横比填充:

btn.contentHorizontalAlignment = .fill
btn.contentVerticalAlignment = .fill
btn.imageView?.contentMode = .scaleAspectFill

答案 12 :(得分:0)

当我为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
  }
}