ฉันจะวางรูปภาพทางด้านขวาของข้อความใน 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
@ การแปล Zoltan ไม่ได้เป็นปัญหาเพียงแค่กลับคุณสมบัติขึ้นอยู่กับสถานที่ปัจจุบัน
manmal

561

วิธีที่ง่ายที่สุด:

iOS 10 ขึ้นไป, 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)

ก่อน 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 น่าสนใจ ... ฉันสามารถเดาได้ว่านี่เป็นเพราะการแปลงเป็นภาพเคลื่อนไหวภายในสำหรับแอนิเมชั่นป๊อปแอนิเมชั่น
Liau Jian Jie

1
ผมพบว่าถ้าเรื่องนี้เป็นสาเหตุของข้อร้องเรียนเกี่ยวกับความขัดแย้ง autolayout จำกัด ที่รันไทม์มันอาจจะได้รับการแก้ไขโดยการเพิ่มใน layoutSubviews ()
ลาด

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 อย่างง่ายดายเพียงพอ
Lee Richardson

268

อัปเดตสำหรับ XCODE 9 (ผ่านตัวสร้างอินเตอร์เฟส)

มีวิธีที่ง่ายกว่าจากเป็นInterface Builder

เลือก UIButton และเลือกตัวเลือกนี้ใน View Utilities> Semantic :

จากซ้ายไปขวา ป้อนคำอธิบายรูปภาพที่นี่ แค่นั้นแหละ! ดีและเรียบง่าย!

ทางเลือก - ขั้นตอนที่ 2:

หากคุณต้องการปรับระยะห่างระหว่างรูปภาพและชื่อคุณสามารถเปลี่ยนImage Inset ได้ที่นี่:

ป้อนคำอธิบายรูปภาพที่นี่

หวังว่าจะช่วย!


2
ใน Xcode 9.0 beta 5 (9M202q) คุณโชคไม่ดีที่เห็นเฉพาะผลลัพธ์ที่รันไทม์ - ในกระดานเรื่องราวที่ยังคงแสดงภาพทางด้านซ้าย นอกจากนี้โปรดทราบว่าด้วยเหตุนี้จึงต้องใช้การทดลองและข้อผิดพลาดบางอย่างเพื่อตั้งค่าสิ่งที่ถูกต้อง
PDK

3
โปรดอย่าทำเช่นนี้ - นี่เป็นการแบ่งภาษาท้องถิ่นสำหรับภาษาจากขวาไปซ้าย
jsadler

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
Hola Soy Edu Feliz 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

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 directlyและbackgroundRectForBoundsSubclasses ที่ให้การตกแต่งพื้นหลังที่กำหนดเองสามารถแทนที่วิธีนี้และส่งกลับขอบเขตที่ปรับเปลี่ยนเพื่อป้องกันไม่ให้ปุ่มวาดเนื้อหาที่กำหนดเองใด ๆ วิธีการ แต่ฉันคิดว่าพวกเขาไม่สนใจ subclasses
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];ก่อน ความกว้างอาจเป็นศูนย์ถ้าคุณยังไม่ได้เรียกใช้เค้าโครง กันไปสำหรับขนาดของภาพ (เพียงแค่ใช้ UIImage.size แทนขนาด IMAGE ดู) ที่
delrox

@ 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 Roué

ฉันต้องวางมันลงlayoutSubviewsในUITableViewCellคลาสย่อย แต่ก็ใช้งานได้ดี ขอบคุณ!
RyanG

60

คำตอบทั้งหมดเหล่านี้ ณ เดือนมกราคม 2559 นั้นไม่จำเป็น ในเครื่องมือสร้างอินเทอร์เฟซตั้งค่ามุมมองความหมายเป็นForce Right-to-Leftหรือถ้าคุณชอบวิธีการเขียนโปรแกรมsemanticContentAttribute = .forceRightToLeftซึ่งจะทำให้รูปภาพปรากฏทางด้านขวาของข้อความของคุณ


5
น่าเศร้าที่มันไม่รองรับ iOS ที่มีอายุมากกว่า 9 ปีคำตอบที่ดียังคงเป็นเช่นนั้น
Eddie

1
ฉันเสียใจที่ต้องรายงานว่าการตั้งค่านี้ใน UIButton ที่ใช้สำหรับ UIBarButtonItem ไม่ได้ทำให้เกิดการเปลี่ยนแปลงใด ๆ
Amelia

ดังที่ @Amelia พูดถึงมันไม่ทำงานหากคุณโทรUIBarButtonItem(customView: button)แต่จะใช้งานได้หากคุณตัดปุ่มในมุมมองที่ว่างเปล่า
tt.Kilew

@ tt.Kilew โดยใช้ XCode 8.1 คุณทำให้มันทำงานได้ ฉันตั้งค่า uiButton.semanticContentAttribute = .forceRightToLeft แล้วให้ nextButton = UIBarButtonItem (customView: uiButton)
Eugene Biryukov

53

ในเครื่องมือสร้างอินเตอร์เฟสคุณสามารถกำหนดค่าตัวเลือก Edge Insets สำหรับ UIButton โดยแยกแต่ละส่วนได้สามส่วน: เนื้อหารูปภาพชื่อเรื่อง

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

Xcode 8:

ป้อนคำอธิบายรูปภาพที่นี่


3
จริง ๆ คำตอบที่ดีที่สุดในมุมมองของฉันstackoverflow.com/a/39013315/1470374นี้ ))
Gennadiy Ryabkin

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
นอกจากนี้คุณสามารถเพิ่ม IBDESIGNABLE ไปยังส่วนหัวของชั้นเรียนเพื่อดูได้ใน Storyborad yadi.sk/i/fd6Si-BJqzCFD
Nikolay 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

Swift- ขยาย 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);

ขอบคุณ Piotr สำหรับทางออกของคุณ!

เอริค


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

    }
}

สำหรับการออกแบบกระดานเรื่องราว UI

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


มีวิธีที่จะทำมันได้อย่างสง่างามมากขึ้น?
Zaporozhchenko Oleksandr


2

คำตอบของ Took @ Piotr และทำให้มันกลายเป็นส่วนขยายที่รวดเร็ว ตรวจสอบให้แน่ใจว่าตั้งค่ารูปภาพและชื่อเรื่องก่อนเรียกสิ่งนี้เพื่อให้ปุ่มมีขนาดที่เหมาะสม

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

โซลูชั่นการโอนย้ายข้อมูลswift 3.0มอบให้โดย 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

ฉันตัดสินใจที่จะไม่ใช้มุมมองภาพปุ่มมาตรฐานเพราะโซลูชั่นที่เสนอเพื่อย้ายไปรอบ ๆ รู้สึกแฮ็ค สิ่งนี้ทำให้ฉันมีสุนทรียภาพที่ต้องการและเป็นเรื่องง่ายที่จะเปลี่ยนตำแหน่งปุ่มโดยการเปลี่ยนข้อ จำกัด :

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;

Caveats: ยังไม่ทดลอง, 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

สำหรับปัญหานี้คุณสามารถสร้าง UIView ภายใน "ป้ายกำกับด้วยมุมมอง UIImage" และตั้งค่าคลาส UIView เป็น UIControl และสร้าง IBAction เหมือนด้านข้าง

ป้อนคำอธิบายรูปภาพที่นี่


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?
Byron Coetsee

ฉันเพิ่งลบยูทิลิตี้มันเป็นชั้นเรียนในรหัสของฉันที่ฉันสามารถตรวจสอบว่าภาษาที่เลือกเป็นภาษาอาหรับหรือภาษาอังกฤษ
ราชิด Latif

0

Xcode 11.4 Swift 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

ฉันลงเอยด้วยการสร้างปุ่มแบบกำหนดเองซึ่งอนุญาตให้ตั้งค่ารูปภาพจากตัวตรวจสอบ ด้านล่างเป็นรหัสของฉัน:

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

คุณสามารถปรับค่าของช่องว่างภายในจากสารวัตรเพื่อปรับระยะห่างระหว่างข้อความและภาพ

PS: ใช้ส่วนของรหัสจาก @Mark Hennings

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.