UIButton에서 텍스트의 오른쪽에 이미지를 어떻게 배치합니까?


300

피할 수 있으면 하위보기를 사용하고 싶지 않습니다. UIButton배경 이미지, 텍스트 및 이미지가있는 이미지를 원합니다 . 지금 내가 그렇게 할 때 이미지는 텍스트의 왼쪽에 있습니다. 배경 이미지, 텍스트 및 이미지는 모두 서로 다른 강조 표시 상태를 갖습니다.


확장 목록에 다른 "해킹"을 추가하려면 여기에서 버튼 제목이있는 버튼을 공백 + 이미지 (NSTextAttachment로)를 포함하는 문자열로 설정할 수 있습니다. 첨부 파일의 경계를 조정하여 원하는대로 정렬해야 할 수도 있습니다 ( stackoverflow.com/questions/26105803/… 참조 ).
Manav

답변:


266

제안 된 답변 중 일부는 매우 독창적이고 매우 영리하지만 가장 간단한 해결책은 다음과 같습니다.

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

저것과 같이 쉬운. 보너스로 이미지는 왼쪽에서 오른쪽에서 왼쪽으로 나타납니다.

편집 : 질문이 몇 번 요청되었으므로 이것은 iOS 9 + 입니다.


89
나는이 대답이 받아 들여 졌다는 것을 믿을 수 없다. 아무도 응용 프로그램에 대한 현지화를 수행하지 않습니까?
Zoltán

6
@pallzoltan : 이것은 질문에 대답합니다 (예 : "UIButton에서 텍스트의 오른쪽에 이미지를 어떻게 배치합니까?"). 현지화는 이것과 어떤 관련이 있습니까?
Benjamin

17
RTL 언어로 레이아웃을 "플립"하지 않으려는 상황은 많지 않습니다. 직접 설정 semanticContentAttribute은 실제 솔루션이 아닌 해킹 / 해결 방법입니다.
Zoltán

6
내 접근 방식은 질문을하는 사람이 무엇을 만들고 있는지 알지 못하므로 항상 레이아웃의 유연성으로 계산하는 것이 좋습니다.
Zoltán

2
@ Zoltán 지역화는 문제가 아니며 현재 지역에 따라 속성을 반전시킵니다.
manmal

561

가장 간단한 해결책 :

iOS 10 이상, 스위프트 :

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)

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
탐색 표시 줄 제목보기에 이것을 사용했고 결함이있었습니다. 처음로드되면 괜찮지 만 뷰 컨트롤러를 밀어서 튀기면 제목이 뒤집 힙니다.
funct7

@WoominJoshPark Interesting ... 트랜스 폼이 내비게이션 팝 애니메이션을 위해 내부적으로 애니메이션되기 때문입니다.
Liau Jian Jie

1
이것이 런타임에 자동 레이아웃 제약 조건 충돌에 대해 불만을 제기하는 경우 layoutSubviews ()에 추가하여 해결할 수 있음을 발견했습니다.
Vlad

1
텍스트와 이미지 사이에 더 많은 공간을 두려면 어떻게해야합니까?
rohinb

2
@rohinb @ jose920405 패딩을 위해 ImageEdgeInsets 및 ContentEdgeInsets를 설정해보십시오 (반대되어 있음을 명심하십시오). 예를 들면 button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. 그것은 Xamarin에 있지만 Swift / Obj-C로 쉽게 번역해야합니다.
리 리처드슨

268

XCODE 9 용 업데이트 (Via Interface Builder)

Interface Builder 에서 더 쉬운 방법이 있습니다 .

UIButton을 선택하고 View Utilities> Semantic 에서이 옵션을 선택하십시오 .

왼쪽에서 오른쪽으로 여기에 이미지 설명을 입력하십시오 그게 다야! 좋고 간단합니다!

선택 사항 -2 단계 :

이미지와 제목 사이의 간격을 조정하려면 여기 에서 이미지 삽입을 변경할 수 있습니다 .

여기에 이미지 설명을 입력하십시오

희망이 도움이됩니다!


2
Xcode 9.0 베타 5 (9M202q)에서는 불행히도 런타임시 결과 만 볼 수 있습니다. 스토리 보드에서는 여전히 왼쪽에 이미지가 표시됩니다. 또한이 때문에 올바른 삽입을 설정하려면 약간의 시행 착오가 필요합니다.
PDK

3
이렇게하지 마십시오. 오른쪽에서 왼쪽으로 쓰는 언어의 현지화가 중단됩니다.
jsadler 2016 년

169

서브 클래 싱 UIButton은 완전히 불필요합니다. 대신 이미지 삽입물에 대해 높은 왼쪽 삽입 값을 설정하고 제목에 대해 작은 오른쪽 삽입을 설정할 수 있습니다. 이 같은:

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

3
그것은 작동하지만, 당신이 viewDidAppear에 그것을해야 자동 레이아웃과하지의 viewDidLoad에 오늘을 기억
안녕 간장 에듀 펠리 즈 Navidad입니다

91

Inspire48에이 크레딧을 제공 하고 있습니다. 그의 제안을 바탕으로 다른 질문을 보면서 나는 이것을 생각해 냈습니다. 서브 클래스 UIButton을 사용하고 이러한 메소드를 대체하십시오.

@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은 클래스 클러스터이므로 서브 클래스 화하면 안됩니다.
Scott Berrevoets 0시 18 분

50
사실은 문서가 서브 클래스를 명시 적으로 언급하고 사용자 정의 레이아웃 동작에 대해 재정의해야하는 메소드를 제공합니다.
Tark

2
developer.apple.com/library/ios/documentation/uikit/reference/… 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 directlybackgroundRectForBounds사용자 정의 배경 장식을 제공하는 서브 클래스는이 메소드를 무시하고 수정 된 경계 사각형을 반환하여 버튼이 사용자 정의 컨텐츠 위에 그려지지 않도록 할 수 있습니다 .` 메소드를 사용하지만 하위 클래스를 신경 쓰지 않는다고 가정합니다.
christophercotton

1
이 공식은 이미지 프레임을 미러링하는 데 더 좋습니다 : 다른 것들을 frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;위해 더 잘 작동 UIControlContentHorizontalAlignmentCenter합니다 ...
k06a

@ GwendalRoué 짧아도 더 좋다는 의미는 아닙니다. 해커 방식이므로 버튼이 실제 삽입을 무시하고 오른쪽에서 왼쪽 언어로 깨질 수 있습니다. 이 답변으로 레이아웃을 완전히 제어 할 수 있습니다
Accatyyc

76

제목이 변경되면 삽입물 만 업데이트하십시오. 반대쪽에 똑같은 반대쪽 삽입물로 삽입물을 보정해야합니다.

[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
[thebutton.titleLabel sizeToFit];전에 추가하고 싶을 수도 있습니다 . 레이아웃을 트리거하지 않은 경우 너비가 0 일 수 있습니다. 이미지 크기도 마찬가지입니다 (imageView 크기 대신 UIImage.size를 사용하십시오)

@delrox 좋은 지적. 사용 가능 titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(또는 아직 설정되지 않은 버튼 프레임에 대해 우려되는 경우 높이에 CGFLOAT_MAX 사용) 및imageWidth = self.currentImage.size.width;
Dave Goldman

1
viewDidLayoutSubviews에 완벽하게 작동
Gwendal 난봉꾼

나는이를 배치했다 layoutSubviews내에서 UITableViewCell서브 클래스 있지만 작업 좋아요. 감사!
RyanG

60

2016 년 1 월 현재 이러한 답변은 모두 불필요합니다. Interface Builder에서 View Semantic을로 설정 Force Right-to-Left하거나 프로그래밍 방식을 선호하는 경우 semanticContentAttribute = .forceRightToLeft이미지가 텍스트 오른쪽에 나타납니다.


5
슬프게도 9보다 오래된 iOS는 지원하지 않습니다. 그래도 좋은 대답입니다.
Eddie

1
UIBarButtonItem에 사용되는 UIButton에서 이것을 설정해도 아무런 변화가 없었습니다.
Amelia

@Amelia가 언급 한 바와 같이 전화 할 경우, 작동하지 않습니다 UIBarButtonItem(customView: button),하지만 당신은 약간의 빈 내부보기 버튼을 포장하는 경우 작동합니다
tt.Kilew

@ tt.Kilew, XCode 8.1을 사용하면 작동합니다. uiButton.semanticContentAttribute = .forceRightToLeft를 설정하고 let nextButton = UIBarButtonItem (customView : uiButton)
Eugene Biryukov를 제공


25

업데이트 : 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
    }
}

Swift 2에 대한 원래 답변 :

Swift 구현 예제를 사용하여 모든 수평 정렬을 처리하는 솔루션. 필요한 경우 Objective-C로 변환하십시오.

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

또한 이미지 및 제목 삽입물을 잘 처리한다는 점도 주목할 가치가 있습니다.

Jasongregori의 답변에서 영감을 얻었습니다.)


1
이 솔루션은 저에게 효과적이지만 이미지에 약간의 공간이 필요하므로 다음 코드를 추가했습니다. self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603

1
@IBDesignable클래스에 추가 하고 디자인 타임에 뒤집힌 것을 볼 수 있기 때문에이 방법이 마음에 듭니다.
James Toomey

탐색 모음에 넣을 때도 작동하기 때문에이 솔루션을 선호합니다.
El Horrible

10

이러한 요구가에서 수행 할 경우 UIBarButtonItem ,보기에서 추가 포장이 사용되어야한다
이 의지 작업을

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)

이 작동하지 않습니다

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

다음은 UIButton중앙 정렬 컨텐츠를 위한 솔루션입니다 . 이 코드는 이미지를 올바르게 정렬하고 사용 imageEdgeInsets하고 titleEdgeInsets소중한 위치를 지정할 수 있도록합니다 .

여기에 이미지 설명을 입력하십시오

UIButton커스텀 클래스로 서브 클래스를 만들고 다음을 추가하십시오.

- (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
또한 당신은 storyborad에서 그것을보기 위해 클래스 헤더에 IBDESIGNABLE을 추가 할 수 있습니다 yadi.sk/i/fd6Si-BJqzCFD
니콜라이 Shubenkov

6

변환 솔루션이 iOS 11에서 작동하지 않기 때문에 새로운 접근법을 작성하기로 결정했습니다.

버튼 조정 semanticContentAttribute 텍스트가 바뀌더라도 릴레이 아웃하지 않고도 이미지를 오른쪽으로 멋지게 볼 수 있습니다. 이 때문에 이상적인 솔루션입니다. 그러나 여전히 RTL 지원이 필요합니다. 앱이 동일한 세션에서 앱의 레이아웃 방향을 변경할 수 없다는 사실이이 문제를 쉽게 해결합니다.

그렇게 말하면 꽤 간단합니다.

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

6

확장 방법

확장 기능을 사용하여 사용자 정의 오프셋으로 오른쪽에 이미지 설정

   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

스위프트-UiButton을 확장 하고이 줄을 넣습니다.

    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

Piotr Tomasik의 우아한 솔루션을 기반으로 : 버튼 레이블과 이미지 사이에 약간의 간격두고 싶다면 다음과 같이 가장자리 삽입 부분에 다음을 포함하십시오 (내 코드를 복사하면 완벽하게 작동합니다).

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

솔루션에 감사드립니다.

에릭


@lulian : 최근에 Liau Jian Jie의 솔루션을 사용하고 있으며 (여기에서 받아 들여진 대답) 훌륭하게 작동하며 매우 우아한 솔루션입니다.
Erik van der Neut

텍스트의 정렬을 변경하므로 나에게 도움이되지 않습니다.
Iulian Onofrei

3

스스로 행동하십시오. Xcode10, swift4,

프로그래밍 방식으로 UI 디자인

여기에 이미지 설명을 입력하십시오

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

모서리 삽입 값은 사각형에 적용되어 해당 사각형으로 표시되는 영역을 축소하거나 확장합니다. 일반적으로 모서리 레이아웃은 뷰 레이아웃 중에 뷰의 프레임을 수정하는 데 사용됩니다. 양수 값을 지정하면 프레임이 지정된 양만큼 삽입되거나 축소됩니다. 음수 값을 지정하면 지정된 양만큼 프레임이 시작되거나 확장됩니다.

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 )

    }
}

StoryBoard UI 디자인

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오


더 우아하게 할 수있는 방법이 있습니까?
Zaporozhchenko Oleksandr


2

@Piotr의 답변을 받아 Swift 확장으로 만들었습니다. 호출하기 전에 이미지와 타이틀을 설정하여 버튼 크기가 올바르게 설정되도록하십시오.

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

삽입물을 사용하지 않고 원하는 것을 수행하는 빠른 옵션 :

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

자동 레이아웃을 활성화하면 여기에 언급 된 솔루션이 작동을 멈췄습니다. . 나는 내 자신을 생각해 내야했다.

서브 클래스 UIButton 및 재정의 layoutSubviews메소드 :

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

}

결과:

여기에 이미지 설명을 입력하십시오


1

jasongregori가 제공하는 swift 3.0 마이그레이션 솔루션

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

나는 표준 버튼 이미지보기를 사용하지 않기로 결정했습니다. 이것은 나에게 원하는 미학을 얻었고, 제약 조건을 변경하여 버튼의 위치를 ​​바꾸는 것이 직관적입니다.

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

오른쪽 화살표가있는 버튼


이것은 탭에 반응하지 않고 텍스트는 어두워 지지만 이미지는 그렇지 않습니다
Teddy K

0

스위프트 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

제약은 어떻습니까? semanticContentAttribute와 달리 의미를 변경하지 않습니다. 아마도 이런 것 :

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

또는 Objective-C에서 :

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

주의 사항 : 테스트되지 않은 iOS 9 이상


0

UIButton 내에서 이미지를 오른쪽 정렬하려면 아래 코드를 시도하십시오

btn.contentHorizontalAlignment = .right

이것은 저자가 요구 한 것이 아닙니다.
Mateusz

0

인터넷에서 여러 솔루션을 시도한 후 정확한 요구 사항을 달성하지 못했습니다. 그래서 사용자 정의 유틸리티 코드를 작성했습니다. 미래에 누군가를 돕기 위해 게시. 신속한 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

이 문제를 위해 "UIImage 뷰가있는 레이블"내에 UIView를 만들고 UIView 클래스를 UIControl로 설정하고 IBAction을 tuch up으로 만들 수 있습니다.

여기에 이미지 설명을 입력하십시오


0

스위프트 4 & 5

UIButton 이미지의 방향 변경 (RTL 및 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)
    }
}

무엇입니까 Utility?
바이런 Coetsee

방금 유틸리티를 제거합니다. 선택한 언어가 아랍어인지 영어인지 확인할 수있는 코드의 클래스입니다.
Rashid Latif

0

Xcode 11.4 스위프트 5.2

다음과 같이 갈매기 모양으로 뒤로 버튼 스타일을 반영하려는 사람은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

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

이행:

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

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

0

결국 Inspector에서 이미지를 설정할 수있는 사용자 정의 버튼을 만들었습니다. 아래는 내 코드입니다.

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

Inspector에서 Gap Padding의 값을 조정하여 텍스트와 이미지 사이의 간격을 조정할 수 있습니다.

추신 : @ Mark Hennings answer의 일부 코드 사용

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.