ナビゲーションバー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

    }

ここに画像の説明を入力してください


ナビゲーションバーでスタックビューを使用しましたか?
Vlad Khambir 2017年

@ V.Khambir Nop ...:/
ロレンゾゴンザレス2017年

このバグレポートはどこにありますか?
Edu

iOS 11はAutoLayoutを使用してナビゲーション項目をレイアウトします。UIButton内側をシフトする必要がある場合はUIBarButtonItembutton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)
onmyway133を

回答:


188

理由

UIBarButtonItemiOS 11 以降では、フレームを処理する代わりに自動レイアウトを使用するため、問題が発生します。

解決

Xcode 9を使用する場合は、この画像ボタンに幅の制約を追加する必要があります。

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

PS

buttonありませんUIBarButtonItem、それはUIButtonUIBarButtonItemです。制約はに対してUIBarButtonItemではなく、その内部の要素に対して設定する必要があります。


3
@ V.Khambir今私はこの問題を抱えています。しかし、xcode 9を使用したこの同じソリューションでは、iOS 1デバイスで実行した場合は問題ありません。これのすべてのバージョンをどのように修正できますか?iOS 11、iOS 10の両方のデバイスをチェックインしました。iOS1バージョンでのみ問題ありません。iOS 10では、画像がまったく表示されない
david

@spikesa、両方のiOSバージョンで動作するはずです。おそらく、誤った制約が設定されています。
Vlad Khambir 2017年

@ V.Khambirタイプ 'UIBarButtonItem'の値には、if #available(iOS 11.0、*)条件付きのXcode 9のメンバー 'widthAnchor'がありませんか?
Ryan Brodie

1
@jpedはこれに対する解決策を見つけましたか?Xcode 9が
インストールさ

1
すごい。お奨めは、これらの重大な変更を気に入っています。アップルはこれらの種類の変更のリストをページまたはリリースノートのどこかに記載しましたか?
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 2017

9
UINavigationBarは、自動レイアウトを使用してサブビューをレイアウトするようになりました
mangerlahn

2
私がしたのと同じ過ちを犯さないでください。オフにしてtranslatesAutoresizingMaskIntoConstraintsから、iOS 9を完全に破損していることがわかりました(ただし、iOS 10および11では問題なく見えました)
xaphod

2
Value of type 'UIBarButtonItem' has no member 'widthAnchor'if #available(iOS 11.0, *)条件付きのXcode 9では?
Ryan Brodie

@ lorenzo-gonzalezどうやって丸くしたの?私はこれにこだわっています。
アレッサンドロルカリーニ

18

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は、ストーリーボードのナビゲーションバーアイテムをランダムにサイズ変更し続けます。変更をプッシュする前に毎回再確認する必要があります。これが最終的にすぐに修正されることを願っています。
Karoly Nyisztor 2017

あなたは私のヒーローです。なぜなら、私は古いプロジェクトを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うまく機能します。
Alessandro Ornano

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、ボタンの位置を設定できます。これで問題なく動作します。


これは機能しますが、ビューに追加するとボタンは機能しなくなります。任意のヒント?
エオニスト、2017年

@GitSyncビューの高さを確認し、0になるようにして、44または必要なものに変更し、clipToBound = trueにしてからボタンを設定します。
iPatel 2017年

1
ワオ。動作します!プロヒント:代わりに使用.PNGの.PDF資産を
eonist

コンテナビューは必要ですか?UIButtonを直接使用することはできませんか?
igrek

5

widthAnchor/ heightAnchorを変更すると、iOS 11以降のデバイスでのみ機能します。iOS 10デバイスの場合、フレームを手動で変更する従来の方法を実行する必要があります。重要なことは、2つのアプローチのどちらも両方のバージョンで機能しないため、以下のように、ランタイムバージョンに応じてプログラムで交互に切り替える必要があります。

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でそれを理解できませんでした
Clifton Labrum '20

3

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

3

iOS 11.Xを実行しているユーザーにとって、制約をプログラムで設定することは私にとってうまくいきました。ただし、iOS 10.Xを実行しているユーザーのために、バーボタンはまだ引き伸ばされていました。AppStoreレビューアがiOS 11.Xを実行していたため、問題を特定できなかったため、アプリを販売する準備ができてアップロードされました。

私の解決策は、別のソフトウェアで画像のサイズを30x30に変更することでした(以前の画像サイズは120x120でした)。


1
ios10のナビゲーションバーは自動サイズ変更され、ios11は自動レイアウトであるため、if #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の画像です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.