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


этот код работает нормально в ios10. я получаю свою метку и кнопку изображения, которая является профилем фотографии пользователя, круговой круг.. ладно. но при запуске в Xcode 9 ios11 симулятор я его выбросила. рамка кнопки должна быть 32x32 , при проверке на sim-карте и получении представления и сообщении xcode для описания представления я получаю вывод как 170x32 или что-то в этом роде.

heres мой код.

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

    }

12 91

12 ответов:

причина

проблема появляется, потому что из ios 11 UIBarButtonItem использует автозапуск вместо работы с кадрами.

решение

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

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

PS

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

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

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

код Objective C теперь устарел. Но для пользователя, который должен создавать / поддерживать проекты Objective C в iOS 11, есть следующий перевод из Swift ( Karoly Nyisztor ответ) к цели 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];

новое barButtonItem использует автозапуск вместо работы с кадрами.

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

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

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

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

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;

спасибо удачи в кодировании!!

Что Я Сделал?

в моем приложении я добавил изображение профиля на навигационной панели в rightbarbutton item. до iOS 11 он работал хорошо и отображался правильно, но при обновлении до iOS 11 затем измените поведение, например blow

enter image description here

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

enter image description here

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

enter image description here enter image description here

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

Примечание: если ваша кнопка не будет работать, то проверьте ваш UIView's высота может быть его 0 здесь вы должны изменить высоту 0 до 44 или что вы хотите. А также сделать clipToBound = true, теперь вы можете установить свой положение кнопки и она будет работать хорошо.

изменение 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 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

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

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

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

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

    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.