панель навигации rightbaritem ошибка кнопки изображения iOS 11

Этот код работает нормально в ios10. я получаю свою метку и кнопку изображения, которая является профилем фотографии пользователя, круглой формы.. хорошо. но при запуске симулятора xcode 9 ios11 я растягиваю его. рамка кнопки должна быть 32x32 , при проверке сима и получении представления и указании 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

    }

введите описание изображения здесь


person lorenzo gonzalez    schedule 08.06.2017    source источник
comment
Вы использовали представление стека в панели навигации?   -  person Vlad Khambir    schedule 09.06.2017
comment
@В.Хамбир Нет... :/   -  person lorenzo gonzalez    schedule 13.06.2017
comment
этот отчет об ошибке где-нибудь?   -  person Edu    schedule 27.09.2017
comment
iOS 11 использует AutoLayout для размещения элементов навигации. Если вам нужно переместить UIButton внутрь UIBarButtonItem, используйте button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)   -  person onmyway133    schedule 06.02.2018


Ответы (12)


Причина

Проблема возникает из-за того, что с ios 11 UIBarButtonItem вместо работы с фреймами использует autolayout.

Решение

Вы должны добавить ограничение ширины для этой кнопки изображения, если вы используете Xcode 9.

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

ПС

button не UIBarButtonItem, это UIButton внутри UIBarButtonItem. Вы должны установить ограничение не для UIBarButtonItem, а для элементов внутри него.

person Vlad Khambir    schedule 09.06.2017
comment
@ В.Хамбир, теперь я получаю эту проблему. Но с тем же решением с xcode 9, и если я запускаю устройство ios 1, все в порядке. Как я могу исправить для всех версий для этого . Я проверил устройство на обоих ios 11, ios 10. Показывает хорошо только в версии ios 1. в ios 10 изображение вообще не отображается - person david; 03.10.2017
comment
@spikesa, это должно работать на обеих версиях iOS, возможно, вы установили неправильные ограничения. - person Vlad Khambir; 03.10.2017
comment
@V.Khambir Значение типа «UIBarButtonItem» не имеет члена «widthAnchor» в Xcode 9 внутри условия if # available (iOS 11.0, *)? - person Ryan Brodie; 06.10.2017
comment
@V.Khambir, похоже, это не работает ни на чем ниже iOS 11. Как исправить это для iOS 9 и 10? - person jped; 13.10.2017
comment
@jped ты нашел решение для этого? У меня это тоже не работает на iOS 10 с Xcode 9 - person swalkner; 16.10.2017
comment
Обновление @jped: теперь я вижу, что кнопка есть, но в самом верху моего приложения; панель инструментов находится внизу, так что с координатой y что-то не так... - person swalkner; 16.10.2017
comment
@jped Update2: в iOS 10 мне нужно установить centerYAnchor на одну из панелей инструментов, чтобы он работал, в iOS 11 он вылетает из-за этого - странно. - person swalkner; 16.10.2017
comment
@V.Khambir Я использовал следующий код, чтобы установить элемент левой и правой кнопки панели навигации: ` navigationItem.rightBarButtonItem = UIBarButtonItem(title: , style: .plain, target: self, action: #selector(submit)) navigationItem .rightBarButtonItem?.image = UIImage(named: tick) navigationItem.leftBarButtonItem = UIBarButtonItem(title:, style: .plain, target: self, action: #selector(dismissview)) navigationItem.leftBarButtonItem?.image = UIImage(named: cancel )` . Как внести вышеуказанные изменения в этот код - person Samarth Kejriwal; 03.11.2017
comment
Отлично. Должен любить эти критические изменения. Apple задокументировала список этих типов изменений на странице или где-нибудь в примечаниях к выпуску? - person GONeale; 06.11.2017

Спасибо всем за участие! вы, ребята, правы!. для xcode9 ios11 вам нужно поставить ограничение.

 let widthConstraint = button.widthAnchor.constraint(equalToConstant: 32)
 let heightConstraint = button.heightAnchor.constraint(equalToConstant: 32)
 heightConstraint.isActive = true
 widthConstraint.isActive = true
person lorenzo gonzalez    schedule 15.06.2017
comment
Это сработало и для меня, но может ли кто-нибудь объяснить, почему это необходимо для iOS 11, когда этого никогда не было раньше? - person stonedauwg; 09.08.2017
comment
UINavigationBar теперь размещает свои подвиды с помощью Auto Layout. - person mangerlahn; 21.08.2017
comment
Не совершайте ту же ошибку, что и я: я выключил translatesAutoresizingMaskIntoConstraints, а позже обнаружил, что это полностью сломало iOS 9 (но выглядело нормально на iOS 10 и 11). - person xaphod; 19.09.2017
comment
Value of type 'UIBarButtonItem' has no member 'widthAnchor' в Xcode 9 внутри условного выражения if #available(iOS 11.0, *)? - person Ryan Brodie; 06.10.2017
comment
@lorenzo-gonzalez Как ты справился? Я застрял на этом. - person Alessandro Lucarini; 30.01.2018
comment
@AlessandroLucarini сделать круглую часть легко: button.layer.cornerRadius = 0,5 * button.bounds.size.width, button.clipsToBounds = true, конечно, должны быть ограничения по высоте и ширине в соотношении 1: 1 .. 32x32, 50x50..и т.д.. .. дайте знать как получилось! - person lorenzo gonzalez; 30.01.2018
comment
Да, я не понял, что я должен добавить линии ограничения вместо замены секции рамы. Спасибо за совет. - person Alessandro Lucarini; 31.01.2018
comment
@ Алессандро Лукарини, у тебя все заработало? Пришлите мне свой код на [email protected], я посмотрю... - person lorenzo gonzalez; 01.02.2018

Код Objective C устарел. Но для пользователя, который должен создавать/обслуживать проекты Objective C в iOS 11, будет полезен следующий перевод со Swift (ответ Кароли Ньистор) на 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];
person SHS    schedule 21.09.2017
comment
Прохладно. На самом деле, мне нужна была и версия для Objective-C. Кстати, Xcode 9 продолжает случайным образом изменять размеры элементов панели навигации в раскадровке. Я должен перепроверять каждый раз, прежде чем вносить свои изменения. Надеюсь, что это скоро будет исправлено. - person Karoly Nyisztor; 21.09.2017
comment
ты мой герой, потому что мне нужно рефакторить старый проект с Objective-C. - person Marosdee Uma; 29.03.2018

Что ж, новый barButtonItem использует авторазметку вместо работы с фреймами.

Изображение, которое вы добавляли к кнопке, больше размера самой кнопки. Поэтому сама кнопка растянулась до размера изображения. Вы должны изменить размер изображения, чтобы оно соответствовало необходимому размеру кнопки, прежде чем добавлять его к кнопке.

person Ahmad Farrag    schedule 09.06.2017

Я написал крошечное расширение для установки ограничений для элементов панели навигации:

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))
person Karoly Nyisztor    schedule 19.09.2017
comment
Отличная идея! Применив это, UIButton работает очень хорошо. - person Alessandro Ornano; 29.01.2018

Я сделал это объективно, используя следующие строки:

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;

Спасибо Удачного кодирования!!

person Aleem    schedule 29.09.2017

Что я сделал?

В моем приложении я добавил изображение профиля на панель навигации в элементе rightBarButton. до iOS 11 он работал хорошо и отображался правильно, но при обновлении до iOS 11 поведение изменилось, например, удар

введите здесь описание изображения

Итак, я добавил UIView в элемент правой кнопки и установил UIButton в качестве подвида UIView? Как показано ниже,

введите здесь описание изображения

И я установил ограничения по высоте и ширине UIButton.

введите здесь описание изображения введите здесь описание изображения

И моя проблема решена. Не забудьте установить цвет фона UIView как чистый цвет.

ПРИМЕЧАНИЕ. Если ваша кнопка не работает, проверьте, может ли высота UIView's быть равной 0. Здесь вы должны изменить высоту 0 на 44< /strong> или что хотите. А также сделайте clipToBound = true, теперь вы можете установить положение вашей кнопки, и она будет работать хорошо.

person iPatel    schedule 06.10.2017
comment
Это работает, однако кнопка перестает работать, когда вы добавляете ее в представление. Какие-нибудь советы? - person Sentry.co; 15.11.2017
comment
@GitSync Проверьте высоту вашего представления, она будет равна 0, измените ее на 44 или на что хотите, сделайте clipToBound = true, а затем установите кнопку. - person iPatel; 15.11.2017
comment
Ух ты. работает! Совет для профессионалов: используйте ресурсы .pdf вместо .png - person Sentry.co; 15.11.2017
comment
нужно ли представление контейнера? Разве я не могу просто использовать UIButton напрямую? - person igrek; 05.01.2018

Изменение 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
}
person Malloc    schedule 18.12.2017
comment
Спасибо за совет по iOS 10! У меня работало исправление iOS 11, но я не мог понять его для iOS 10. - person Clifton Labrum; 20.12.2017

Несмотря на то, что 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
person Leszek Zarna    schedule 20.09.2017

Установка ограничений программным образом сработала для пользователей iOS 11.X. Тем не менее, кнопка панели по-прежнему была растянута для пользователей с iOS 10.X. Я полагаю, что рецензенты AppStore работали под управлением iOS 11.X, поэтому не смогли идентифицировать мою проблему, поэтому мое приложение было готово к продаже и загружено ..

Мое решение состояло в том, чтобы просто изменить размеры моего изображения на 30x30 в другом программном обеспечении (предыдущий размер изображения был 120x120).

person Erik Nguyen    schedule 22.10.2017
comment
Поскольку панель навигации в ios10 автоматически изменяет размер, а ios11 — в автоматическом макете, вам нужно обработать if # available(iOS 11, *){ } - person Paulo Sigales; 03.11.2017
comment
Я просматривал новые изменения и нашел этот вопрос, но этот ответ, я думаю, должен использовать разработчик - person Shobhakar Tiwari; 21.11.2017
comment
Отличный, простой ответ. Спасибо. Больше ничего не работало, и это сводило меня с ума. - person Brittany; 15.12.2017

Я также добился успеха, реализовав intrinsicContentSize для возврата соответствующего размера для любого пользовательского подкласса UIView, который я намереваюсь использовать в качестве customView.

person Chris    schedule 19.09.2017

Я создал элемент кнопки панели, а затем добавил его на панель навигации.

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

В представленииDidLoad()

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

Здесь у меня есть изображение 28x28.

person vinny    schedule 17.09.2018