【问题标题】:navigation bar rightbaritem image-button bug iOS 11导航栏 rightbaritem 图像按钮错误 iOS 11
【发布时间】:2017-11-10 13:45:30
【问题描述】:

此代码在 ios10 中运行正常。我得到我的标签和一个图像按钮,这是用户照片配置文件,圆形圆形.. 好的。但是当运行 xcode 9 ios11 模拟器时,我把它拉长了。按钮框架必须是 32x32 ,当检查 sim 并获取视图并告诉 xcode 描述视图时,我得到的输出为 170x32 或类似的东西。

这是我的代码。

let labelbutton = UIButton( type: .system)
    labelbutton.addTarget(self, action:#selector(self.toLogin(_:)), for: .touchUpInside)
    labelbutton.setTitleColor(UIColor.white, for: .normal)
    labelbutton.contentHorizontalAlignment = .right
    labelbutton.titleLabel?.font = UIFont.systemFont(ofSize: 18.00)



    let button = UIButton(type: .custom)
     button.addTarget(self, action:#selector(self.toLogin(_:)), for: .touchUpInside)
     button.frame = CGRect(x: 0, y: 0, width: 32, height: 32)
     button.setTitleColor(UIColor.white, for: .normal)
     button.setTitleColor(UIColor.white, for: .highlighted)


    var buttomItem : UIBarButtonItem = UIBarButtonItem()
    buttomItem.customView = button
    buttomItem.target = self
    buttomItem.action = "ToLogin"

    var labelItem : UIBarButtonItem = UIBarButtonItem()
    labelItem.customView = labelbutton
    labelItem.target = self
    labelItem.action = "ToLogin"


    if let user = PFUser.current() {
        print("LOGIN : checkiando si existe usuario ")
            labelbutton.setTitle(USERNAME, for: UIControlState.normal)
            labelbutton.sizeToFit()

        if(user["profile_photo_url"] != nil) {
            print(" ENCONTRO PROFILE PHOTO URL NOT NIL Y ES \(user["profile_photo_url"])")
            let photoURL = user["profile_photo_url"] as! String
            let a = LoginService.sharedInstance
            a.downloadImage(url: photoURL, complete: { (complete) in

                if (complete) {

                    button.setImage(LoginService.sharedInstance.profile_photo! , for: UIControlState.normal)

                    button.layer.cornerRadius = 0.5 * button.bounds.size.width
                   // button.imageView!.contentMode = .scaleAspectFit
                   // button.imageView!.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
                    //button.imageView!.contentMode = .scaleAspectFit
                    //button.imageView!.clipsToBounds = true
                    //button.imageView!.layer.cornerRadius = 60
                    button.clipsToBounds = true
                    self.NavigationItem.rightBarButtonItems = [buttomItem,labelItem]
                }


            })
        } else {
                self.NavigationItem.rightBarButtonItem = labelItem

        }
            print(" EL FRAME DEL BUTTON ES \(button.frame)")

    } else {

        labelbutton.setTitle("Login", for: UIControlState.normal)
        labelbutton.sizeToFit()
        self.NavigationItem.rightBarButtonItem = labelItem

    }

【问题讨论】:

  • 你在导航栏中使用了堆栈视图吗?
  • @V.Khambir Nop... :/
  • 此错误报告是否存在?
  • iOS 11 使用 AutoLayout 来布局导航项。如果您需要在UIBarButtonItem 中移动UIButton,请使用button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)

标签: ios swift ios11 xcode9-beta swift4


【解决方案1】:

原因

出现问题是因为从 ios 11 UIBarButtonItem 开始使用自动布局而不是处理帧。

解决方案

如果你使用 Xcode 9,你应该为这个图像按钮添加宽度限制。

 button.widthAnchor.constraint(equalToConstant: 32.0).isActive = true
 button.heightAnchor.constraint(equalToConstant: 32.0).isActive = true

附言

button 不是UIBarButtonItem,它是UIButtonUIBarButtonItem 里面。您不应该为UIBarButtonItem 设置约束,而是为其中的元素设置约束。

【讨论】:

  • @V.Khambir 现在我遇到了这个问题。但是使用与 xcode 9 相同的解决方案,如果我在 ios 1 设备中运行它很好..但是如果我在 ios 10 版本设备中运行..我的条形按钮图像 r 根本没有显示。我该如何解决这个问题的所有版本。我检查了 ios 11、ios 10 的设备。仅在 ios 1 版本中显示良好。在 ios 10 中,图像根本不显示
  • @spikesa,它应该适用于两个 iOS 版本,可能你设置了不正确的约束。
  • @V.Khambir 类型“UIBarButtonItem”的值在 Xcode 9 中在 if #available(iOS 11.0, *) 条件下没有成员“widthAnchor”?
  • @jped 你找到解决方案了吗?它在带有 Xcode 9 的 iOS 10 上也不适用于我
  • 太棒了。一定要喜欢这些突破性的变化。 Apple 是否在某个页面或发行说明中记录了这些类型的更改列表?
【解决方案2】:

感谢大家的贡献!你们是对的!对于 xcode9 ios11 你需要设置一个约束。

 let widthConstraint = button.widthAnchor.constraint(equalToConstant: 32)
 let heightConstraint = button.heightAnchor.constraint(equalToConstant: 32)
 heightConstraint.isActive = true
 widthConstraint.isActive = true

【讨论】:

  • 这对我也有用,但谁能解释为什么这对 iOS 11 来说是必要的,而以前从未如此?
  • UINavigationBar 现在使用自动布局来布局其子视图
  • 不要犯我犯的同样错误:我关闭了translatesAutoresizingMaskIntoConstraints,后来发现它完全破坏了 iOS 9(但在 iOS 10 和 11 上看起来很好)
  • Value of type 'UIBarButtonItem' has no member 'widthAnchor' 在 Xcode 9 中的 if #available(iOS 11.0, *) 条件内?
  • @lorenzo-gonzalez 你是怎么做到的?我被困在这上面了。
【解决方案3】:

Objective C 代码现在已过时。但是对于必须在 iOS 11 中构建/维护 Objective C 项目的用户,有以下来自 Swift 的翻译( Karoly Nyisztor 回答)对 Objective C 很有帮助。

//  UIView+Navbar.h

#import <UIKit/UIKit.h>

@interface UIView (Navbar)

- (void)applyNavBarConstraints:(CGFloat)width height:(CGFloat)height;

@end

//----------

//  UIView+Navbar.m

#import "UIView+Navbar.h"

@implementation UIView (Navbar)

- (void)applyNavBarConstraints:(CGFloat)width height:(CGFloat)height
{
    if (width == 0 || height == 0) {
        return;
    }

    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height];
    NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:width];
    [heightConstraint setActive:TRUE];
    [widthConstraint setActive:TRUE];
}

//----------

// Usage :-
[button applyNavBarConstraints:33 height:33];

【讨论】:

  • 酷。实际上,我也需要 Objective-C 版本。顺便说一句,Xcode 9 不断随机调整故事板中导航栏项目的大小。每次推送更改之前,我都必须仔细检查。希望这最终能很快得到解决。
  • 你是我的英雄,因为我需要用objective-c重构旧项目。
【解决方案4】:

嗯,新的barButtonItem 使用自动布局而不是处理帧。

您添加到按钮的图像大于按钮本身的大小。这就是按钮本身被拉伸到图像大小的原因。在将图像添加到按钮之前,您必须调整图像大小以匹配所需按钮的大小。

【讨论】:

    【解决方案5】:

    我写了一个小扩展来设置导航栏项目的约束:

    import UIKit
    
    extension UIView {
        func applyNavBarConstraints(size: (width: CGFloat, height: CGFloat)) {
        let widthConstraint = self.widthAnchor.constraint(equalToConstant: size.width)
        let heightConstraint = self.heightAnchor.constraint(equalToConstant: size.height)
        heightConstraint.isActive = true
        widthConstraint.isActive = true
      }
    }
    
    // Usage
    button.applyNavBarConstraints(size: (width: 33, height: 33))
    

    【讨论】:

    • 好主意!应用这个UIButton 效果很好。
    【解决方案6】:

    我使用以下几行客观地做到了这一点:

    NSLayoutConstraint * widthConstraint = [customButton.widthAnchor constraintEqualToConstant:40];
    NSLayoutConstraint * HeightConstraint =[customButton.heightAnchor constraintEqualToConstant:40];
    [widthConstraint setActive:YES];
    [HeightConstraint setActive:YES];
    
    UIBarButtonItem* customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customButton];
    self.navigationItem.leftBarButtonItem = customBarButtonItem;
    

    感谢快乐编码!

    【讨论】:

      【解决方案7】:

      我做了什么?

      在我的应用程序中,我在导航栏的 rightBarButton 项上添加了个人资料图片。在 iOS 11 之前它运行良好并且显示正常,但是当更新到 iOS 11 时就会改变行为,比如打击

      所以我在右键项目中添加了UIView 并将UIButton 设置为UIView 的子视图?如下所示,

      我设置了UIButton的高度和宽度限制。

      我的问题解决了。不要忘记将UIView的背景颜色设置为clear颜色。

      注意:如果您的按钮不起作用,请检查您的 UIView's 高度可能是它的 0 在这里您应该将高度 0 更改为44 或任何你想要的。还有clipToBound = true,现在你可以设置按钮的位置,它会很好用。

      【讨论】:

      • 这可行,但是当您将其添加到视图中时,该按钮将停止工作。有什么建议吗?
      • @GitSync 检查您的视图高度,它将为 0 将其更改为 44 或您想要的任何值,并使 clipToBound = true 然后设置按钮。
      • 哇。作品!专业提示:使用 .pdf 资产而不是 .png
      • 容器视图是否必要?我不能直接使用 UIButton 吗?
      【解决方案8】:

      更改 widthAnchor/heightAnchor 仅适用于 iOS 11+ 设备。对于 iOS 10 设备,您需要采用手动更改框架的经典方式。问题是这两种方法都不适用于两个版本,因此您绝对需要根据运行时版本以编程方式交替,如下所示:

      if #available(iOS 11.0, *)
      {
         button.widthAnchor.constraint(equalToConstant: 32.0).isActive = true
         button.heightAnchor.constraint(equalToConstant: 32.0).isActive = true
      }else
      {
         var frame = button.frame
         frame.size.width = 32.0
         frame.size.height = 32.0
         button.frame = frame
      }
      

      【讨论】:

      • 感谢 iOS 10 提示!我已经修复了 iOS 11,但无法解决 iOS 10 的问题。
      【解决方案9】:

      即使 iOS 11 使用 Autolayout 作为导航栏,也可以让它以传统方式设置框架。这是我适用于 ios11 和 ios10 或更早版本的代码:

      func barItemWithView(view: UIView, rect: CGRect) -> UIBarButtonItem {
          let container = UIView(frame: rect)
          container.addSubview(view)
          view.frame = rect
          return UIBarButtonItem(customView: container)
      }
      

      这是条形项目的组成方式:

          let btn = UIButton()
          btn.setImage(image.withRenderingMode(.alwaysTemplate), for: .normal)
          btn.tintColor = tint
          btn.imageView?.contentMode = .scaleAspectFit
          let barItem = barItemWithView(view: btn, rect: CGRect(x: 0, y: 0, width: 22, height: 22))
          return barItem
      

      【讨论】:

        【解决方案10】:

        以编程方式为运行 iOS 11.X 的用户设置约束对我有用。 但是,对于运行 iOS 10.X 的用户,条形按钮仍然被拉伸。 我猜 AppStore 审核人员运行的是 iOS 11.X,因此无法识别我的问题,所以我的应用准备好销售并上传了..

        我的解决方案是在另一个软件中将我的图像尺寸简单地更改为 30x30(之前的图像尺寸是 120x120)。

        【讨论】:

        • 因为ios10中的导航栏是自动调整大小而ios11是自动布局,所以需要用if #available(iOS 11, *){ }
        • 我正在经历新的变化,我发现了这个问题,但我猜开发人员应该使用这个答案
        • 很好,简单的答案。谢谢你。没有其他工作,这让我发疯。
        【解决方案11】:

        我还通过实现intrinsicContentSize 为我打算用作 customView 的任何自定义 UIView 子类返回适当的大小而取得了成功。

        【讨论】:

          【解决方案12】:

          我创建了一个栏按钮项,然后将其添加到导航栏。

              private var addItem: UIBarButtonItem = {
                  let addImage = UIImage(named: "add")
                  let addButton = UIButton(type: UIButton.ButtonType.custom)
                  addButton.setBackgroundImage(addImage, for: UIControl.State())
                  addButton.frame = CGRect(x: 0, y: 0, width: (addImage?.size.width)!, height: (addImage?.size.height)!)
                  let addItem = UIBarButtonItem(customView: addButton)
                  return addItem
              }()
          
           private var contactsItem: UIBarButtonItem = {
                  let contactsImage = UIImage(named: "contacts")
                  let contactsButton = UIButton(type: UIButton.ButtonType.custom)
                  contactsButton.setBackgroundImage(contactsImage, for: UIControl.State())
                  contactsButton.frame = CGRect(x: 0, y: 0, width: (contactsImage?.size.width)!, height: (contactsImage?.size.height)!)
                  let contactsItem = UIBarButtonItem(customView: contactsButton)
                  return contactsItem
              }()
          

          在 viewDidLoad() 中

          let spacerBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: nil, action: nil)
                  spacerBarButtonItem.width = 11
                  navigationItem.rightBarButtonItems = [addItem, spacerBarButtonItem, contactsItem]
          

          我这里有 28x28 的图像。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-14
            • 1970-01-01
            • 2013-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多