Làm cách nào để đặt hình ảnh ở bên phải văn bản trong UIButton?


300

Tôi không muốn sử dụng một cuộc phỏng vấn nếu tôi có thể tránh nó. Tôi muốn một UIButtonhình ảnh nền, văn bản và hình ảnh trong đó. Ngay bây giờ, khi tôi làm điều đó, hình ảnh nằm ở bên trái của văn bản. Hình nền, văn bản và hình ảnh đều có các trạng thái nổi bật khác nhau.


Để thêm một "hack" khác vào danh sách đang phát triển ở đây: bạn có thể đặt AttributionTitle của nút thành một chuỗi được gán có chứa tiêu đề nút của bạn + dấu cách + hình ảnh (dưới dạng NSTextAttachment). Bạn có thể cần phải điều chỉnh giới hạn của tệp đính kèm để làm cho nó căn chỉnh theo ý muốn (xem stackoverflow.com/questions/26105804/ - ).
Manav

Câu trả lời:


266

Mặc dù một số câu trả lời được đề xuất là rất sáng tạo và cực kỳ thông minh, giải pháp đơn giản nhất như sau:

button.semanticContentAttribute = UIApplication.shared
    .userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft

Đơn giản vậy thôi. Như một phần thưởng, hình ảnh sẽ ở phía bên trái trong các địa điểm từ phải sang trái.

EDIT : như câu hỏi đã được hỏi một vài lần, đây là iOS 9 + .


89
Tôi không thể tin câu trả lời này là câu trả lời được chấp nhận. Không ai bản địa hóa cho các ứng dụng của họ?
Zoltán

6
@pallzoltan: điều này trả lời câu hỏi (ví dụ: "Làm cách nào để đặt hình ảnh ở bên phải của văn bản trong một UIButton?"). Điều gì đã nội địa hóa phải làm với điều này?
Benjamin

17
Không có nhiều tình huống khi bạn không muốn bố cục của mình bị "lật" trong các ngôn ngữ RTL. Cài đặt trực tiếp semanticContentAttributechỉ là một hack / cách giải quyết, không phải là một giải pháp thực sự.
Zoltán

6
Cách tiếp cận của tôi là bạn không biết người hỏi câu hỏi đang xây dựng cái gì, vì vậy nó luôn được tính tốt hơn với sự linh hoạt cho bố cục.
Zoltán

2
@ Zoltán nội địa hóa không phải là một vấn đề, chỉ cần đảo ngược tài sản tùy thuộc vào địa phương hiện tại.
manody

561

Giải pháp đơn giản nhất:

iOS 10 trở lên, Swift:

button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)

Trước iOS 10, Swift / Obj-C:

button.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.titleLabel.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.imageView.transform = CGAffineTransformMakeScale(-1.0, 1.0);

8
Tôi đã sử dụng điều này cho chế độ xem tiêu đề thanh điều hướng và có một trục trặc. Sẽ ổn khi tải lần đầu tiên, nhưng khi bạn nhấn một bộ điều khiển xem và bật nó, tiêu đề sẽ bị lật.
func7

@WoominJoshPark Thú vị ... Tôi chỉ có thể đoán rằng điều này là do biến đổi được hoạt hình bên trong cho hoạt hình pop điều hướng.
Liau Jian Jie

1
Tôi đã tìm thấy nếu điều này gây ra khiếu nại về xung đột ràng buộc tự động thanh toán khi chạy, nó có thể được khắc phục bằng cách thêm phần này vào layoutSubview ()
Vlad

1
Làm thế nào tôi có thể đặt nhiều không gian hơn giữa văn bản và hình ảnh?
rohinb

2
@rohinb @ jose920405 Hãy thử đặt ImageEdgeInsets và ContentEdgeInsets để đệm (lưu ý rằng chúng đã bị đảo ngược). Ví dụ button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. Đó là trong Xamarin, nhưng nên dịch sang Swift / Obj-C đủ dễ dàng.
Lee Richardson

268

CẬP NHẬT CHO XCODE 9 (Thông qua Trình tạo giao diện)

Có một cách dễ dàng hơn từ Trình tạo giao diện .

Chọn UIButton và chọn tùy chọn này trong Xem Tiện ích> Ngữ nghĩa :

từ trái sang phải nhập mô tả hình ảnh ở đây Đó là nó! Đẹp và đơn giản!

TÙY CHỌN - Bước 2:

Nếu bạn muốn điều chỉnh khoảng cách giữa hình ảnh và tiêu đề, bạn có thể thay đổi Inset hình ảnh ở đây:

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

Mong rằng sẽ giúp!


2
Trong Xcode 9.0 beta 5 (9M202q), thật không may, bạn chỉ thấy kết quả trong thời gian chạy LỚN trong bảng phân cảnh, nó vẫn hiển thị hình ảnh bên trái. Cũng lưu ý rằng vì điều này cần một số thử nghiệm và lỗi để đặt các phần tử chính xác.
PDK

3
Xin đừng làm theo cách này - điều này phá vỡ nội địa hóa cho các ngôn ngữ từ phải sang trái.
jsadler

169

Phân lớp UIButton là hoàn toàn không cần thiết. Thay vào đó, bạn có thể chỉ cần đặt giá trị chèn bên trái cao cho các hình ảnh và một hình nhỏ bên phải cho tiêu đề. Một cái gì đó như thế này:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);

3
Nó đã hoạt động, nhưng chỉ cần nhớ rằng hôm nay với tính năng tự động thanh toán, bạn phải thực hiện nó trên viewDidAppear chứ không phải trên viewDidLoad
Hola Soy Edu Feliz Navidad

91

Tôi đang cho Inspire48 tín dụng cho cái này. Dựa trên đề nghị của anh ấy và nhìn vào câu hỏi khác tôi đã nghĩ ra điều này. Phân lớp UIButton và ghi đè các phương thức này.

@implementation UIButtonSubclass

- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super imageRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) -  self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMinX(frame) - CGRectGetWidth([self imageRectForContentRect:contentRect]);
    return frame;
}

@end

3
UIButton là một cụm lớp và không nên được phân lớp.
Scott Berrevoets

50
Điều đó không đúng, tài liệu đề cập rõ ràng việc phân lớp và cung cấp các phương thức bạn nên ghi đè cho hành vi bố cục tùy chỉnh.
Tark

2
developer.apple.com/l Library / ios / document / uikit / report / Bậc buttonWithType If you subclass UIButton, this method does not return an instance of your subclass. If you want to create an instance of a specific subclass, you must alloc/init the button directlyvà các backgroundRectForBoundslớp con cung cấp trang trí nền tùy chỉnh có thể ghi đè phương thức này và trả về hình chữ nhật giới hạn đã sửa đổi để ngăn nút vẽ lên bất kỳ nội dung tùy chỉnh nào. phương thức, nhưng tôi giả sử họ không nhớ các lớp con.
christopherc Bông

1
Có vẻ như công thức này tốt hơn cho việc phản chiếu khung hình ảnh: frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;Nó hoạt động tốt hơn cho UIControlContentHorizontalAlignmentCenternhững người khác ...
k06a

@ GwendalRoué Chỉ vì nó ngắn hơn không có nghĩa là nó tốt hơn. Đó là một cách hackier và nó làm cho nút bỏ qua các phần tử thực tế và có thể phá vỡ các ngôn ngữ từ phải sang trái. Với câu trả lời này, bạn có toàn quyền kiểm soát bố cục
Accatyyc

76

Chỉ cần cập nhật các phần tử khi tiêu đề được thay đổi. Bạn cần phải bù cho hình nhỏ bằng một hình nhỏ bằng nhau và ngược lại ở phía bên kia.

[thebutton setTitle:title forState:UIControlStateNormal];
thebutton.titleEdgeInsets = UIEdgeInsetsMake(0, -thebutton.imageView.frame.size.width, 0, thebutton.imageView.frame.size.width);
thebutton.imageEdgeInsets = UIEdgeInsetsMake(0, thebutton.titleLabel.frame.size.width, 0, -thebutton.titleLabel.frame.size.width);

3
Bạn có thể muốn thêm [thebutton.titleLabel sizeToFit];trước. Chiều rộng có thể bằng 0 nếu bạn chưa kích hoạt bố cục. Tương tự với kích thước hình ảnh (chỉ cần sử dụng UIImage.size thay vì kích thước imageView)
delrox

@delrox điểm tốt. Có thể sử dụng titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(hoặc nếu bạn lo ngại về khung nút chưa được thiết lập, hãy sử dụng CGFLOAT_MAX cho chiều cao) vàimageWidth = self.currentImage.size.width;
Dave Goldman

1
Hoạt động hoàn hảo trên viewDidLayoutSubview
Gwendal Roué

Tôi đã phải đặt nó trong lớp con layoutSubviewscủa tôi UITableViewCellnhưng nó hoạt động tốt. Cảm ơn!
RyanG

60

Tất cả những câu trả lời này, kể từ tháng 1 năm 2016, là không cần thiết. Trong Trình tạo giao diện, đặt Chế độ xem ngữ nghĩa thành Force Right-to-Lefthoặc nếu bạn thích cách lập trình, semanticContentAttribute = .forceRightToLeftĐiều đó sẽ khiến hình ảnh xuất hiện ở bên phải văn bản của bạn.


5
Đáng buồn thay, nó không hỗ trợ ios cũ hơn 9. Vẫn là câu trả lời hay, tho.
Eddie

1
Tôi rất buồn khi báo cáo rằng việc cài đặt này trên UIButton sau đó được sử dụng cho UIBarButtonItem không dẫn đến bất kỳ thay đổi nào.
Amelia

Như @Amelia đã đề cập, nó không hoạt động nếu bạn gọi UIBarButtonItem(customView: button), nhưng sẽ hoạt động nếu bạn quấn nút bên trong một số chế độ xem trống
tt.Kilew

@ tt.Kilew, sử dụng XCode 8.1 bạn sẽ làm cho nó hoạt động. Tôi đặt uiButton.semanticContentAttribution = .forceRightToLeft và cung cấp let nextButton = UIBarButtonItem (customView: uiButton)
Eugene Biryukov


25

Cập nhật: Swift 3

class ButtonIconRight: UIButton {
    override func imageRect(forContentRect contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRect(forContentRect: contentRect)
        imageFrame.origin.x = super.titleRect(forContentRect: contentRect).maxX - imageFrame.width
        return imageFrame
    }

    override func titleRect(forContentRect contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRect(forContentRect: contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX
        }
        return titleFrame
    }
}

Câu trả lời gốc cho Swift 2:

Một giải pháp xử lý tất cả các sắp xếp theo chiều ngang, với ví dụ triển khai Swift. Chỉ cần dịch sang Objective-C nếu cần.

class ButtonIconRight: UIButton {
    override func imageRectForContentRect(contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRectForContentRect(contentRect)
        imageFrame.origin.x = CGRectGetMaxX(super.titleRectForContentRect(contentRect)) - CGRectGetWidth(imageFrame)
        return imageFrame
    }

    override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRectForContentRect(contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = CGRectGetMinX(super.imageRectForContentRect(contentRect))
        }
        return titleFrame
    }
}

Cũng đáng lưu ý rằng nó xử lý khá tốt hình ảnh & tiêu đề.

Lấy cảm hứng từ câu trả lời của jasongregori;)


1
Giải pháp này hiệu quả với tôi, tuy nhiên hình ảnh của tôi cần một khoảng trống xung quanh nó vì vậy tôi đã thêm đoạn mã sau: self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603

1
Tôi thích cách này vì bạn có thể thêm @IBDesignablevào lớp và thấy nó được lật tại thời điểm thiết kế.
James Toomey

Tôi thích giải pháp này vì nó thậm chí hoạt động khi đặt trong thanh điều hướng.
El Hor khiếp

10

Nếu điều này cần được thực hiện trong UIBarButtonItem , nên sử dụng gói bổ sung trong chế độ xem
Điều này sẽ hoạt động

let view = UIView()
let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
view.addSubview(button)
view.frame = button.bounds
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: view)

Điều này sẽ không làm việc

let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)

7

Đây là giải pháp cho UIButtonnội dung phù hợp với trung tâm. Mã này làm cho hình ảnh được căn chỉnh đúng và cho phép sử dụng imageEdgeInsetstitleEdgeInsetscho vị trí quý giá.

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

Lớp UIButtonvới lớp tùy chỉnh của bạn và add:

- (CGRect)imageRectForContentRect:(CGRect)contentRect {
    CGRect frame = [super imageRectForContentRect:contentRect];
    CGFloat imageWidth = frame.size.width;
    CGRect titleRect = CGRectZero;
    titleRect.size = [[self titleForState:self.state] sizeWithAttributes:@{NSFontAttributeName: self.titleLabel.font}];
    titleRect.origin.x = (self.frame.size.width - (titleRect.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    frame.origin.x = titleRect.origin.x + titleRect.size.width - self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    CGFloat imageWidth = [self imageForState:self.state].size.width;
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    return frame;
}

1
Ngoài ra, bạn có thể thêm IBDESIGNABLE vào tiêu đề lớp để xem nó trong Storyborad yadi.sk/i/fd6Si-BJqzCFD
Nikolay Shubenkov

6

Do giải pháp chuyển đổi không hoạt động trong iOS 11, tôi quyết định viết một cách tiếp cận mới.

Điều chỉnh các nút semanticContentAttribute cho chúng ta hình ảnh độc đáo ở bên phải mà không phải chuyển tiếp nếu văn bản thay đổi. Bởi vì đây là giải pháp lý tưởng. Tuy nhiên tôi vẫn cần hỗ trợ RTL. Thực tế là một ứng dụng không thể thay đổi hướng bố cục của nó trong cùng một phiên sẽ giải quyết vấn đề này một cách dễ dàng.

Như đã nói, nó khá dễ dàng.

extension UIButton {
    func alignImageRight() {
        if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
            semanticContentAttribute = .forceRightToLeft
        }
        else {
            semanticContentAttribute = .forceLeftToRight
        }
    }
}

6

Cách mở rộng

Sử dụng tiện ích mở rộng để đặt hình ảnh ở phía bên phải với độ lệch tùy chỉnh

   extension UIButton {
    func addRightImage(image: UIImage, offset: CGFloat) {
        self.setImage(image, for: .normal)
        self.imageView?.translatesAutoresizingMaskIntoConstraints = false
        self.imageView?.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
        self.imageView?.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -offset).isActive = true
    }
}

4

Swift - Mở rộng UiButton và đặt các dòng này

    if let imageWidth = self.imageView?.frame.width {
        self.titleEdgeInsets = UIEdgeInsetsMake(0, -imageWidth, 0, imageWidth);
    }

    if let titleWidth = self.titleLabel?.frame.width {
        let spacing = titleWidth + 20
        self.imageEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, -spacing);
    }

3

Xây dựng dựa trên giải pháp tao nhã của Piotr Tomasik: nếu bạn muốn có một chút khoảng cách giữa nhãn nút và hình ảnh , thì hãy đưa nó vào phần bên trong của bạn như sau (sao chép mã của tôi ở đây phù hợp với tôi):

    CGFloat spacing          = 3;
    CGFloat insetAmount      = 0.5 * spacing;

    // First set overall size of the button:
    button.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
    [button sizeToFit];

    // Then adjust title and image insets so image is flipped to the right and there is spacing between title and image:
    button.titleEdgeInsets   = UIEdgeInsetsMake(0, -button.imageView.frame.size.width - insetAmount, 0,  button.imageView.frame.size.width  + insetAmount);
    button.imageEdgeInsets   = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width + insetAmount, 0, -button.titleLabel.frame.size.width - insetAmount);

Cảm ơn Piotr cho giải pháp của bạn!

Erik


@lulian: Tôi đã sử dụng giải pháp Liau Jian Jie gần đây (câu trả lời được chấp nhận ở đây), và nó hoạt động rất tốt và là một giải pháp rất thanh lịch.
Erik van der Neut

Điều đó cũng không hiệu quả với tôi vì nó thay đổi sự liên kết của văn bản.
Iulian Onofrei

3

Tự làm. Xcode10, swift4,

Đối với thiết kế UI lập trình

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

 lazy var buttonFilter : ButtonRightImageLeftTitle = {
    var button = ButtonRightImageLeftTitle()
    button.setTitle("Playfir", for: UIControl.State.normal)
    button.setImage(UIImage(named: "filter"), for: UIControl.State.normal)
    button.backgroundColor = UIColor.red
    button.contentHorizontalAlignment = .left
    button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
    return button
}()

Các giá trị chèn cạnh được áp dụng cho hình chữ nhật để thu nhỏ hoặc mở rộng diện tích được biểu thị bằng hình chữ nhật đó. Thông thường, các cạnh trong được sử dụng trong bố cục khung nhìn để sửa đổi khung của khung nhìn. Các giá trị dương làm cho khung hình được chèn (hoặc thu nhỏ) theo số lượng được chỉ định. Các giá trị âm làm cho khung được đặt ngoài (hoặc mở rộng) theo số lượng được chỉ định.

class ButtonRightImageLeftTitle: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        guard imageView != nil else { return }

        imageEdgeInsets = UIEdgeInsets(top: 5, left: (bounds.width - 35), bottom: 5, right: 5)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: -((imageView?.bounds.width)! + 10), bottom: 0, right: 0 )

    }
}

cho thiết kế UI StoryBoard

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


Có cách nào để làm điều đó thanh lịch hơn?
Zaporozhchenko Oleksandr


2

Lấy câu trả lời của @ Piotr và biến nó thành một phần mở rộng Swift. Hãy chắc chắn để đặt hình ảnh và tiêu đề trước khi gọi này, để kích thước nút đúng.

extension UIButton {

/// Makes the ``imageView`` appear just to the right of the ``titleLabel``.
func alignImageRight() {
    if let titleLabel = self.titleLabel, imageView = self.imageView {
        // Force the label and image to resize.
        titleLabel.sizeToFit()
        imageView.sizeToFit()
        imageView.contentMode = .ScaleAspectFit

        // Set the insets so that the title appears to the left and the image appears to the right. 
        // Make the image appear slightly off the top/bottom edges of the button.
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -1 * imageView.frame.size.width,
            bottom: 0, right: imageView.frame.size.width)
        self.imageEdgeInsets = UIEdgeInsets(top: 4, left: titleLabel.frame.size.width,
            bottom: 4, right: -1 * titleLabel.frame.size.width)
    }
}

}


2

Một tùy chọn nhanh chóng thực hiện những gì bạn muốn mà không cần chơi với bất kỳ nội dung nào:

class RightImageButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let  textSize = titleLabel?.intrinsicContentSize(),
                imageSize = imageView?.intrinsicContentSize() {
            let wholeWidth = textSize.width + K.textImageGap + imageSize.width
            titleLabel?.frame = CGRect(
                x: round(bounds.width/2 - wholeWidth/2),
                y: 0,
                width: ceil(textSize.width),
                height: bounds.height)
            imageView?.frame = CGRect(
                x: round(bounds.width/2 + wholeWidth/2 - imageSize.width),
                y: RoundRetina(bounds.height/2 - imageSize.height/2),
                width: imageSize.width,
                height: imageSize.height)
        }
    }

    struct K {
        static let textImageGap: CGFloat = 5
    }

}

1

Các giải pháp được đề cập ở đây đã ngừng hoạt động, khi tôi bật Tự động bố trí . Tôi đã phải tự nghĩ ra:

layoutSubviewsPhương pháp UIButton phân lớp và ghi đè :

//
//  MIThemeButtonImageAtRight.m
//  Created by Lukasz Margielewski on 7/9/13.
//

#import "MIThemeButtonImageAtRight.h"

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets);

@implementation MIThemeButtonImageAtRight

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect contentFrame = CGRectByApplyingUIEdgeInsets(self.bounds, self.contentEdgeInsets);

    CGRect frameIcon = self.imageView.frame;
    CGRect frameText = self.titleLabel.frame;

    frameText.origin.x = CGRectGetMinX(contentFrame) + self.titleEdgeInsets.left;
    frameIcon.origin.x = CGRectGetMaxX(contentFrame) - CGRectGetWidth(frameIcon);

    self.imageView.frame = frameIcon;
    self.titleLabel.frame = frameText;
}

@end

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets){

    CGRect f = frame;

    f.origin.x += insets.left;
    f.size.width -= (insets.left + insets.right);
    f.origin.y += (insets.top);
    f.size.height -= (insets.top + insets.bottom);

    return f;

}

Kết quả:

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


1

giải pháp di chuyển swift 3.0 được đưa ra bởi jasongregori

class ButtonIconRight: UIButton {
        override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
            var imageFrame = super.imageRect(forContentRect: contentRect)
           imageFrame.origin.x = super.titleRect(forContentRect: contentRect).maxX - imageFrame.width
        return imageFrame
        }

        override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
            var titleFrame = super.titleRect(forContentRect: contentRect)
            if (self.currentImage != nil) {
                titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX
            }
            return titleFrame
        }

1

Tôi quyết định không sử dụng chế độ xem hình ảnh nút tiêu chuẩn vì các giải pháp được đề xuất để di chuyển nó xung quanh cảm thấy bị hack. Điều này mang lại cho tôi tính thẩm mỹ mong muốn và thật trực quan khi định vị lại nút bằng cách thay đổi các ràng buộc:

extension UIButton {
    func addRightIcon(image: UIImage) {
        let imageView = UIImageView(image: image)
        imageView.translatesAutoresizingMaskIntoConstraints = false

        addSubview(imageView)

        let length = CGFloat(15)
        titleEdgeInsets.right += length

        NSLayoutConstraint.activate([
            imageView.leadingAnchor.constraint(equalTo: self.titleLabel!.trailingAnchor, constant: 10),
            imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
            imageView.widthAnchor.constraint(equalToConstant: length),
            imageView.heightAnchor.constraint(equalToConstant: length)
        ])
    }
}

nút có mũi tên phải


Điều này không đáp ứng với vòi, văn bản mờ đi nhưng hình ảnh thì không
Teddy K

0

Swift 3:

open override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.imageRect(forContentRect: contentRect)
    let  imageWidth = frame.size.width
    var titleRect = CGRect.zero
    titleRect.size = self.title(for: self.state)!.size(attributes: [NSFontAttributeName: self.titleLabel!.font])
    titleRect.origin.x = (self.frame.size.width - (titleRect.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    frame.origin.x = titleRect.origin.x + titleRect.size.width - self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame
}

open override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.titleRect(forContentRect: contentRect)
    if let imageWidth = self.image(for: self.state)?.size.width {
        frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    }
    return frame
}

0

Làm thế nào về ràng buộc? Không giống như semanticContentAttribution, họ không thay đổi ngữ nghĩa. Một cái gì đó như thế này có lẽ:

 button.rightAnchorconstraint(equalTo: button.rightAnchor).isActive = true

hoặc trong Mục tiêu-C:

[button.imageView.rightAnchor constraintEqualToAnchor:button.rightAnchor].isActive = YES;

Hãy cẩn thận: Chưa được kiểm tra, iOS 9+


0

Để căn chỉnh hình ảnh trong UIButton, hãy thử mã bên dưới

btn.contentHorizontalAlignment = .right

Đây không phải là những gì tác giả hỏi về.
Mateusz

0

Sau khi thử nhiều giải pháp từ khắp nơi trên internet, tôi đã không đạt được yêu cầu chính xác. Vì vậy, tôi đã kết thúc bằng cách viết mã tiện ích tùy chỉnh. Đăng bài để giúp đỡ ai đó trong tương lai. Đã thử nghiệm trên swift 4.2

// This function should be called in/after viewDidAppear to let view render
    func addArrowImageToButton(button: UIButton, arrowImage:UIImage = #imageLiteral(resourceName: "my_image_name") ) {
        let btnSize:CGFloat = 32
        let imageView = UIImageView(image: arrowImage)
        let btnFrame = button.frame
        imageView.frame = CGRect(x: btnFrame.width-btnSize-8, y: btnFrame.height/2 - btnSize/2, width: btnSize, height: btnSize)
        button.addSubview(imageView)
        //Imageview on Top of View
        button.bringSubviewToFront(imageView)
    }

0

đối với vấn đề này, bạn có thể tạo UIView bên trong "nhãn với chế độ xem UIImage" và đặt lớp UIView làm UIControl và tạo IBAction khi đặt bên cạnh

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


0

Swift 4 & 5

Thay đổi hướng của hình ảnh UIButton (RTL và LTR)

extension UIButton {
    func changeDirection(){
       isArabic ? (self.contentHorizontalAlignment = .right) : (self.contentHorizontalAlignment = .left)
        // left-right margin 
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }
}

Có gì Utility?
Byron Coetsee

Tôi chỉ xóa Tiện ích, Đây là một lớp trong mã của tôi, nơi tôi có thể kiểm tra xem ngôn ngữ đã chọn là tiếng Ả Rập hay tiếng Anh
Rashid Latif

0

Xcode 11.4 Swift 5.2

Đối với bất cứ ai đang cố gắng phản chiếu kiểu nút Back bằng chevron như thế này:

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

import UIKit

class NextBarButton: UIBarButtonItem {

    convenience init(target: Any, selector: Selector) {

        // Create UIButton
        let button = UIButton(frame: .zero)

        // Set Title
        button.setTitle("Next", for: .normal)
        button.setTitleColor(.systemBlue, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 17)

        // Configure Symbol
        let config = UIImage.SymbolConfiguration(pointSize: 19.0, weight: .semibold, scale: .large)
        let image = UIImage(systemName: "chevron.right", withConfiguration: config)
        button.setImage(image, for: .normal)

        // Add Target
        button.addTarget(target, action: selector, for: .touchUpInside)

        // Put the Image on the right hand side of the button
        // Credit to liau-jian-jie for this part
        button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)

        // Customise spacing to match system Back button
        button.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: -18.0, bottom: 0.0, right: 0.0)
        button.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -12.0, bottom: 0.0, right: 0.0)

        self.init(customView: button)
    }
}

Thực hiện:

override func viewDidLoad() {
    super.viewDidLoad()
    let nextButton = NextBarButton(target: self, selector: #selector(nextTapped))
    navigationItem.rightBarButtonItem = nextButton
}

@objc func nextTapped() {
    // your code
}

0

Tôi đã kết thúc việc tạo một nút tùy chỉnh, cho phép thiết lập Hình ảnh từ Thanh tra. Dưới đây là mã của tôi:

import UIKit

@IBDesignable
class CustomButton: UIButton {

    @IBInspectable var leftImage: UIImage? = nil
    @IBInspectable var gapPadding: CGFloat = 0

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }

    func setup() {

        if(leftImage != nil) {
            let imageView = UIImageView(image: leftImage)
            imageView.translatesAutoresizingMaskIntoConstraints = false

            addSubview(imageView)

            let length = CGFloat(16)
            titleEdgeInsets.left += length

            NSLayoutConstraint.activate([
                imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: gapPadding),
                imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
                imageView.widthAnchor.constraint(equalToConstant: length),
                imageView.heightAnchor.constraint(equalToConstant: length)
            ])
        }
    }
}

Bạn có thể điều chỉnh giá trị của Gap Padding từ Inspector để điều chỉnh khoảng cách giữa văn bản và hình ảnh.

PS: Đã sử dụng một số phần mã từ câu trả lời @Mark Hennings

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.