【问题标题】:UIButton not respect Aspect Fill contentMode after resizing animation调整动画大小后UIButton不尊重Aspect Fill contentMode
【发布时间】: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?

【问题讨论】:

    标签: ios swift ios8


    【解决方案1】:
    1. 将按钮类型设置为 UIButtonTypeCustom(故事板或 xib 中的“自定义”)。
    2. 设置按钮的图像,而不是按钮的背景图像。
    3. 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
                        }
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-07-22
                        • 2013-11-02
                        • 1970-01-01
                        • 2012-08-25
                        • 2022-12-14
                        • 1970-01-01
                        相关资源
                        最近更新 更多