lỗi nút hình ảnh trên thanh điều hướng bên phải iOS 11


101

Mã này hoạt động tốt trong ios10. Tôi nhận được nhãn của mình và một nút hình ảnh là hồ sơ ảnh người dùng, hình tròn .. ok. nhưng khi chạy trình mô phỏng xcode 9 ios11, tôi thấy nó bị kéo dài ra. khung nút phải là 32x32, khi kiểm tra trên sim và nhận được chế độ xem và nói với xcode để mô tả chế độ xem, tôi nhận được đầu ra là 170x32 hoặc một số tương tự.

heres mã của tôi.

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

    }

nhập mô tả hình ảnh ở đây


Bạn đã sử dụng chế độ xem ngăn xếp trong thanh điều hướng?
Vlad Khambir

@ V.Khambir Nop ...: /
lorenzo gonzalez

báo cáo lỗi này có ở đâu không?
Edu

iOS 11 sử dụng Tự động thanh toán để bố trí các mục điều hướng. Trong trường hợp bạn cần phải thay đổi UIButtonbên trong UIBarButtonItem, sử dụngbutton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)
onmyway133

Câu trả lời:


188

Lý do

Sự cố xuất hiện do từ ios 11 UIBarButtonItemsử dụng tính năng tự động thanh toán thay vì xử lý các khung hình.

Giải pháp

Bạn nên thêm ràng buộc chiều rộng cho nút hình ảnh này nếu bạn sử dụng Xcode 9.

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

PS

buttonkhông UIBarButtonItem, nó UIButtonở bên trong UIBarButtonItem. Bạn nên đặt ràng buộc không phải cho UIBarButtonItem, mà cho các phần tử bên trong nó.


3
@ V.Khambir bây giờ tôi đang nhận được vấn đề này. Nhưng với giải pháp tương tự này với xcode 9, và nếu tôi chạy trên thiết bị ios 1 thì nó vẫn ổn. Nhưng nếu tôi chạy trong thiết bị phiên bản ios 10 thì hình ảnh nút thanh của tôi r không hiển thị. Làm thế nào tôi có thể sửa chữa cho tất cả các phiên bản cho điều này Tôi đã kiểm tra thiết bị của cả ios 11, ios 10. Chỉ hiển thị tốt ở phiên bản ios 1. trong ios 10, hình ảnh không hiển thị ở tất cả
david

@spikesa, nó sẽ hoạt động trên cả hai phiên bản iOS, có thể bạn đã đặt các ràng buộc không chính xác.
Vlad Khambir

@ V.Khambir Giá trị của loại 'UIBarButtonItem' không có thành viên 'widthAnchor' trong Xcode 9 bên trong điều kiện if #available (iOS 11.0, *)?
Ryan Brodie

1
@jped bạn đã tìm ra giải pháp cho việc này chưa? Nó không làm việc cho tôi là tốt trên iOS 10 với Xcode 9
swalkner

1
Tuyệt quá. Gotta thích những thay đổi đột phá này. Apple đã ghi lại danh sách các loại thay đổi này trên một trang hoặc ghi chú phát hành ở đâu đó chưa?
GONeale

53

Cảm ơn tất cả vì đã đóng góp! các bạn nói đúng !. đối với xcode9 ios11, bạn cần đặt một hạn chế.

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

1
Điều này cũng hiệu quả với tôi, nhưng có ai có thể giải thích tại sao điều này lại cần thiết cho iOS 11 khi nó chưa từng có trước đây không?
stonedauwg

9
UINavigationBar sao bây giờ bố trí subviews của nó sử dụng Auto Layout
mangerlahn

2
Đừng mắc phải sai lầm giống như tôi đã làm: Tôi tắt translatesAutoresizingMaskIntoConstraintsvà sau đó phát hiện ra rằng hoàn toàn phá vỡ iOS 9 (nhưng nhìn tốt trên iOS 10 và 11)
xaphod

2
Value of type 'UIBarButtonItem' has no member 'widthAnchor'trong Xcode 9 bên trong một if #available(iOS 11.0, *)điều kiện?
Ryan Brodie

@ lorenzo-gonzalez Bạn làm thế nào để làm cho nó tròn? Tôi bị mắc kẹt về điều này.
Alessandro Lucarini

18

Mã Objective C hiện đã lỗi thời. Nhưng đối với người dùng phải xây dựng / duy trì các dự án Objective C trong iOS 11, bản dịch sau đây từ Swift (câu trả lời của Karoly Nyisztor) sang Objective C rất hữu ích.

//  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];

Mát mẻ. Trên thực tế, tôi cũng cần phiên bản Objective-C. Btw, Xcode 9 tiếp tục thay đổi kích thước ngẫu nhiên các mục trên thanh điều hướng trong bảng phân cảnh. Tôi phải kiểm tra lại mỗi lần trước khi thực hiện các thay đổi của mình. Hy vọng điều này cuối cùng sẽ sớm được khắc phục.
Karoly Nyisztor 21/09/17

bạn là anh hùng của tôi, bởi vì tôi cần phải cấu trúc lại dự án cũ với mục tiêu-c.
Marosdee Uma

18

Vâng, The mới barButtonItemsử dụng tự động thanh toán thay vì xử lý các khung.

Hình ảnh bạn đã thêm vào nút lớn hơn kích thước của chính nút đó. Đó là lý do tại sao bản thân nút đã được kéo dài đến kích thước của hình ảnh. Bạn phải thay đổi kích thước hình ảnh để phù hợp với kích thước của nút cần thiết, trước khi thêm nó vào nút.


14

Tôi đã viết một tiện ích mở rộng nhỏ để thiết lập các ràng buộc trên các mục trên thanh điều hướng:

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

Ý tưởng tuyệt vời! Áp dụng một trong những UIButtonhoạt động rất tốt.
Alessandro Ornano

12

Tôi đã thực hiện điều này một cách khách quan bằng cách sử dụng các dòng sau:

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;

Cảm ơn Chúc bạn viết mã vui vẻ !!


7

Tôi đã làm gì?

Trong ứng dụng của mình, tôi đã thêm hình ảnh hồ sơ trên navigationBar tại mục rightBarButton. trước iOS 11 nó hoạt động tốt và hiển thị bình thường nhưng khi cập nhật lên iOS 11 thì thay đổi hành vi như thổi

nhập mô tả hình ảnh ở đây

Vì vậy, tôi đã thêm UIViewvào mục nút bên phải và đặt UIButtonlàm chế độ xem phụ của UIView? Như bên dưới,

nhập mô tả hình ảnh ở đây

Và tôi đặt các giới hạn chiều cao và chiều rộng của UIButton.

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Và vấn đề của tôi đã được giải quyết. Đừng quên đặt UIViewmàu nền của là màu rõ ràng .

LƯU Ý: Nếu nút của bạn không hoạt động thì hãy kiểm tra UIView'schiều cao của bạn có thể là 0 ở đây, bạn nên thay đổi chiều cao 0 thành 44 hoặc bất cứ điều gì bạn muốn. Và cũng làm được clipToBound = true, Bây giờ bạn có thể đặt vị trí nút của mình và Nó sẽ hoạt động tốt.


Điều này hoạt động, tuy nhiên nút ngừng hoạt động khi bạn thêm nó vào một dạng xem. Bất kỳ lời khuyên?
eonist

@GitSync Kiểm tra chiều cao của chế độ xem của bạn, nó sẽ là 0, thay đổi nó thành 44 hoặc bất cứ thứ gì bạn muốn và tạo clipToBound = true rồi đặt nút.
iPatel

1
Chà. làm! Pro tip: tài sản sử dụng .pdf thay vì .png
eonist

chế độ xem vùng chứa có cần thiết không? Tôi không thể chỉ sử dụng UIButton trực tiếp?
igrek

5

Thay đổi widthAnchor/ heightAnchorsẽ chỉ hoạt động trên thiết bị iOS 11+. Đối với thiết bị iOS 10, bạn cần thực hiện theo cách cổ điển là thay đổi khung hình theo cách thủ công. Vấn đề là không có cách nào trong hai cách tiếp cận hoạt động cho cả hai phiên bản, vì vậy bạn hoàn toàn cần phải lập trình thay thế tùy thuộc vào phiên bản thời gian chạy, như dưới đây:

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
Cảm ơn mẹo dành cho iOS 10! Tôi đã sửa chữa iOS 11 làm việc nhưng không thể tìm ra nó dành cho iOS 10
Clifton Labrum

3

Mặc dù iOS 11 sử dụng Autolayout cho thanh điều hướng, nhưng vẫn có thể làm cho nó hoạt động theo cách thiết lập khung theo cách truyền thống. Đây là mã của tôi hoạt động cho ios11 và ios10 trở lên:

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

và đây là cách cấu tạo mục thanh:

    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

Đặt các ràng buộc theo lập trình phù hợp với tôi đối với người dùng chạy iOS 11.X. Tuy nhiên, nút thanh vẫn bị kéo dài đối với người dùng chạy iOS 10.X. Tôi đoán những người đánh giá AppStore đang chạy iOS 11.X do đó không thể xác định được vấn đề của tôi nên ứng dụng của tôi đã sẵn sàng để bán và tải lên ..

Giải pháp của tôi là chỉ cần thay đổi kích thước hình ảnh của tôi thành 30x30 trong một phần mềm khác (kích thước hình ảnh trước đó là 120x120).


1
Vì thanh điều hướng trong ios10 đang tự động kích thước và ios11 là tự động thanh toán, bạn cần xử lý nếu #available (iOS 11, *) {}
Paulo Sigales

Tôi đã đi qua những thay đổi mới và tôi thấy câu hỏi này, nhưng câu trả lời này tôi đoán nhà phát triển nên sử dụng
Shobhakar Tiwari

Câu trả lời tuyệt vời, đơn giản. Cảm ơn bạn. Không có gì khác đang hoạt động và nó làm tôi phát điên.
Brittany

0

Tôi cũng đã thành công khi triển khai intrinsicContentSizeđể trả về kích thước thích hợp cho bất kỳ lớp con UIView tùy chỉnh nào mà tôi định sử dụng làm customView.


0

Tôi đã tạo một mục nút thanh và sau đó thêm nó vào thanh điều hướng.

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

Trong viewDidLoad ()

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

Ở đây tôi có hình ảnh 28x28.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.