导航栏rightbaritem图像按钮错误iOS 11


101

此代码在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 ...:/
lorenzo gonzalez

此错误报告在任何地方吗?
Edu

iOS 11使用自动布局来布局导航项。如果您需要移动UIButton内部UIBarButtonItem,请使用button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)
onmyway133'2

Answers:


188

原因

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

如果使用Xcode 9,则应为此图像按钮添加宽度限制。

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

聚苯乙烯

button不是UIBarButtonItem,它在UIButton内部UIBarButtonItem。您不应为设置约束UIBarButtonItem,而应为其中的元素设置约束。


3
@ V.Khambir现在我遇到了这个问题。但是,使用与xcode 9相同的解决方案,如果我在ios 1设备上运行,它很好..但是,如果我在ios 10版本的设备中运行..我的条形按钮图像根本不显示。我该如何修复所有版本。我签入了两个ios 11,ios 10的设备。仅在ios 1版本中显示良好。在ios 10中,图像完全没有显示
大卫

@spikesa,它应该在两个iOS版本上都可以使用,可能您设置的约束不正确。
弗拉德·康比尔

@ V.Khambir类型为'UIBarButtonItem'的值在条件#available(iOS 11.0,*)中是否在Xcode 9中没有成员'widthAnchor'?
瑞安·布罗迪

1
@jped您是否找到了解决方案?在iOS 10上使用Xcode 9时
它对

1
大。要爱这些重大的变化。Apple是否已在页面或某处的发行说明中记录了这些类型的更改的列表?
GoNeale

53

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

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

1
这也对我有用,但是谁能解释为什么iOS 11以前从未需要这样做?
stonedauwg '17

9
UINavigationBar现在确实使用“自动布局”来布局其子视图
mangerlahn

2
不要犯同样的错误:我关闭电源translatesAutoresizingMaskIntoConstraints,然后发现它完全破坏了iOS 9(但在iOS 10和11上看起来还不错)
xaphod

2
Value of type 'UIBarButtonItem' has no member 'widthAnchor'在Xcode 9中if #available(iOS 11.0, *)有条件吗?
瑞安·布罗迪

@ lorenzo-gonzalez你是怎么做到的?我一直坚持下去。
亚历山德罗·卢卡里尼

18

目标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会继续在情节提要中随机调整导航栏项目的大小。每次推送更改之前,我都必须仔细检查。希望这个问题很快得到解决。
Karoly Nyisztor

您是我的英雄,因为我需要使用Objective-C重构旧项目。
Marosdee Uma,

18

好吧,新版barButtonItem使用自动布局而不是处理框架。

您添加到按钮上的图像大于按钮尺寸本身。这就是为什么按钮本身会拉伸到图像的大小。在将图像添加到按钮之前,必须调整图像的大小以匹配所需按钮的大小。


14

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

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作品效果很好。
亚历山德罗·奥纳诺

12

我客观地做到了以下几点:

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项目的navigationBar上添加了个人资料图片。在iOS 11之前,它运行良好并可以正常显示,但是在更新到iOS 11时,则更改了行为,例如打击

在此处输入图片说明

所以我添加UIView了右键按钮项并设置UIButtonUIView?的子视图?像下面一样

在此处输入图片说明

并且我设置的高度和宽度约束UIButton

在此处输入图片说明 在此处输入图片说明

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

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


此方法有效,但是在视图中添加按钮时该按钮停止工作。有小费吗?
eonist

@GitSync检查视图的高度,将其设置为0或将其更改为0,然后将clipToBound = true设置为true,然后设置按钮。
iPatel '17

1
哇。作品!专家提示:请使用.pdf资产而不是.png
eonist版本

容器视图是否必要?我不能直接使用UIButton吗?
igrek

5

更改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
}

1
感谢iOS 10提示!我有iOS的11修复工作,但无法弄清楚的iOS 10
克利夫顿·拉布兰

3

即使iOS 11将“自动布局”用于导航栏,也可以使其在传统情况下可以设置框架。这是我的适用于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

3

对于运行iOS 11.X的用户,以编程方式放置约束对我来说是有效的。但是,对于运行iOS 10.X的用户,“ bar”按钮仍然处于拉伸状态。我认为AppStore审阅者正在运行iOS 11.X,因此无法识别我的问题,因此我的应用已准备好出售和上载。

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


1
由于ios10中的导航栏是自动调整大小的,而ios11是自动布局,因此您需要使用#available(iOS 11,*){}
Paulo Sigales

我正在经历新的更改,但发现了这个问题,但是我想开发人员应该使用这个答案
Shobhakar Tiwari

很好,简单的答案。谢谢。没有其他工作,这让我发疯。
布列塔尼

0

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


0

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

    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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.