ฉันมีUIButton
ข้อความ "สำรวจแอป" และUIImage
(>) Interface Builder
ดูเหมือนว่า:
[ (>) Explore the app ]
แต่ฉันต้องวางสิ่งนี้ไว้UIImage
หลังข้อความ:
[ Explore the app (>) ]
ฉันจะย้ายUIImage
ไปทางขวาได้อย่างไร?
ฉันมีUIButton
ข้อความ "สำรวจแอป" และUIImage
(>) Interface Builder
ดูเหมือนว่า:
[ (>) Explore the app ]
แต่ฉันต้องวางสิ่งนี้ไว้UIImage
หลังข้อความ:
[ Explore the app (>) ]
ฉันจะย้ายUIImage
ไปทางขวาได้อย่างไร?
คำตอบ:
วิธีแก้ปัญหาของฉันค่อนข้างง่าย
[button sizeToFit];
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);
ในiOS 9เป็นต้นไปดูเหมือนว่าวิธีง่ายๆในการบรรลุเป้าหมายนี้คือการบังคับใช้ความหมายของมุมมอง
หรือโดยใช้โปรแกรมโดยใช้:
button.semanticContentAttribute = .ForceRightToLeft
semanticContentAttribute
ในตรรกะเค้าโครงของเราแทนที่จะเปลี่ยนตัวsemanticContentAttribute
เอง (การเปลี่ยนวิธีการเชิงความหมายจะไม่ทำงานได้ดีกับความเป็นสากล)
ตั้งค่าimageEdgeInset
และtitleEdgeInset
เพื่อย้ายส่วนประกอบรอบ ๆ ภายในภาพของคุณ คุณยังสามารถสร้างปุ่มโดยใช้กราฟิกที่มีขนาดเต็มและใช้เป็นภาพพื้นหลังของปุ่มได้ (จากนั้นใช้titleEdgeInsets
เพื่อเลื่อนชื่อไปรอบ ๆ )
คำตอบของ Raymond W ดีที่สุดที่นี่ Subclass UIButton พร้อมเค้าโครงที่กำหนดเอง ง่ายมากที่จะทำนี่คือรูปแบบการใช้งาน Subviews ที่เหมาะกับฉัน:
- (void)layoutSubviews
{
// Allow default layout, then adjust image and label positions
[super layoutSubviews];
UIImageView *imageView = [self imageView];
UILabel *label = [self titleLabel];
CGRect imageFrame = imageView.frame;
CGRect labelFrame = label.frame;
labelFrame.origin.x = imageFrame.origin.x;
imageFrame.origin.x = labelFrame.origin.x + CGRectGetWidth(labelFrame);
imageView.frame = imageFrame;
label.frame = labelFrame;
}
สิ่งที่เกี่ยวกับคลาสย่อยUIButton
และการลบล้างlayoutSubviews
?
จากนั้นประมวลผลสถานที่ของself.imageView
&self.titleLabel
อีกวิธีง่ายๆ (ที่ไม่ใช่ iOS 9 เท่านั้น) คือซับคลาส UIButton เพื่อแทนที่สองวิธีนี้
override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
var rect = super.titleRectForContentRect(contentRect)
rect.origin.x = 0
return rect
}
override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
var rect = super.imageRectForContentRect(contentRect)
rect.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(rect)
return rect
}
contentEdgeInsets
ถูกนำมาพิจารณาโดยใช้ super
การบังคับให้ "ขวาไปซ้าย" สำหรับปุ่มไม่ใช่ตัวเลือกหากแอปของคุณรองรับทั้ง "ซ้ายไปขวา" และ "ขวาไปซ้าย"
วิธีแก้ปัญหาที่เหมาะกับฉันคือคลาสย่อยที่สามารถเพิ่มลงในปุ่มใน Storyboard และทำงานได้ดีกับข้อ จำกัด (ทดสอบใน iOS 11):
class ButtonWithImageAtEnd: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
if let imageView = imageView, let titleLabel = titleLabel {
let padding: CGFloat = 15
imageEdgeInsets = UIEdgeInsets(top: 5, left: titleLabel.frame.size.width+padding, bottom: 5, right: -titleLabel.frame.size.width-padding)
titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageView.frame.width, bottom: 0, right: imageView.frame.width)
}
}
}
โดยที่ "padding" จะเป็นช่องว่างระหว่างชื่อเรื่องและรูปภาพ
.forceRightToLeft
เป็นตัวเลือก! เพียงแค่ใช้ค่าตรงข้าม ( .forceLeftToRight
) UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft
ถ้า
ใน Swift:
override func layoutSubviews(){
super.layoutSubviews()
let inset: CGFloat = 5
if var imageFrame = self.imageView?.frame,
var labelFrame = self.titleLabel?.frame {
let cumulativeWidth = imageFrame.width + labelFrame.width + inset
let excessiveWidth = self.bounds.width - cumulativeWidth
labelFrame.origin.x = excessiveWidth / 2
imageFrame.origin.x = labelFrame.origin.x + labelFrame.width + inset
self.imageView?.frame = imageFrame
self.titleLabel?.frame = labelFrame
}
}
สร้างคำตอบโดย @split ...
คำตอบนั้นยอดเยี่ยมมาก แต่จะไม่สนใจข้อเท็จจริงที่ว่าปุ่มอาจมีภาพที่กำหนดเองและการตั้งค่าขอบหัวเรื่องที่กำหนดไว้ล่วงหน้า (เช่นในสตอรีบอร์ด)
ตัวอย่างเช่นคุณอาจต้องการให้รูปภาพมีช่องว่างจากด้านบนและด้านล่างของคอนเทนเนอร์ แต่ยังคงย้ายรูปภาพไปทางด้านขวาของปุ่ม
ฉันขยายแนวคิดด้วยวิธีนี้: -
- (void) moveImageToRightSide {
[self sizeToFit];
CGFloat titleWidth = self.titleLabel.frame.size.width;
CGFloat imageWidth = self.imageView.frame.size.width;
CGFloat gapWidth = self.frame.size.width - titleWidth - imageWidth;
self.titleEdgeInsets = UIEdgeInsetsMake(self.titleEdgeInsets.top,
-imageWidth + self.titleEdgeInsets.left,
self.titleEdgeInsets.bottom,
imageWidth - self.titleEdgeInsets.right);
self.imageEdgeInsets = UIEdgeInsetsMake(self.imageEdgeInsets.top,
titleWidth + self.imageEdgeInsets.left + gapWidth,
self.imageEdgeInsets.bottom,
-titleWidth + self.imageEdgeInsets.right - gapWidth);
}
// Get the size of the text and image
CGSize buttonLabelSize = [[self.button titleForState:UIControlStateNormal] sizeWithFont:self.button.titleLabel.font];
CGSize buttonImageSize = [[self.button imageForState:UIControlStateNormal] size];
// You can do this line in the xib too:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
// Adjust Edge Insets according to the above measurement. The +2 adds a little space
self.button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -(buttonLabelSize.width+2));
self.button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, buttonImageSize.width+2);
สิ่งนี้จะสร้างปุ่มที่จัดชิดขวาดังนี้:
[ button label (>)]
ปุ่มไม่ได้ปรับความกว้างตามบริบทดังนั้นช่องว่างจะปรากฏทางด้านซ้ายของป้ายกำกับ คุณสามารถแก้ปัญหานี้ได้โดยคำนวณความกว้างเฟรมของปุ่มจาก buttonLabelSize.width และ buttonImageSize.width
button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
โซลูชันนี้ใช้ได้กับ iOS 7 ขึ้นไป
เพียง UIButton คลาสย่อย
@interface UIButton (Image)
- (void)swapTextWithImage;
@end
@implementation UIButton (Image)
- (void)swapTextWithImage {
const CGFloat kDefaultPadding = 6.0f;
CGSize buttonSize = [self.titleLabel.text sizeWithAttributes:@{
NSFontAttributeName:self.titleLabel.font
}];
self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView.frame.size.width, 0, self.imageView.frame.size.width);
self.imageEdgeInsets = UIEdgeInsetsMake(0, buttonSize.width + kDefaultPadding, 0, -buttonSize.width);
}
@end
การใช้งาน (ที่ไหนสักแห่งในชั้นเรียนของคุณ):
[self.myButton setTitle:@"Any text" forState:UIControlStateNormal];
[self.myButton swapTextWithImage];
สร้างจากคำตอบก่อนหน้านี้ หากคุณต้องการให้มีระยะขอบระหว่างไอคอนและชื่อของปุ่มรหัสจะต้องเปลี่ยนแปลงเล็กน้อยเพื่อป้องกันไม่ให้ป้ายกำกับและไอคอนลอยอยู่เหนือขอบเขตของปุ่มที่มีขนาดภายใน
let margin = CGFloat(4.0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width)
button.contentEdgeInsets = UIEdgeInsetsMake(0, margin, 0, margin)
บรรทัดรหัสสุดท้ายมีความสำคัญสำหรับการคำนวณขนาดเนื้อหาภายในสำหรับโครงร่างอัตโนมัติ
นี่คือวิธีของฉันเองในการทำสิ่งนั้น(หลังจากนั้นประมาณ 10 ปี)
class CustomButton: Button {
var didLayout: Bool = false // The code must be called only once
override func layoutSubviews() {
super.layoutSubviews()
if !didLayout, let imageView = imageView, let titleLabel = titleLabel {
didLayout = true
let stack = UIStackView(arrangedSubviews: [titleLabel, imageView])
addSubview(stack)
stack.edgesToSuperview() // I use TinyConstraints library. You could handle the constraints directly
stack.axis = .horizontal
}
}
}
โซลูชันบรรทัดเดียวใน Swift:
// iOS 9 and Onwards
button.semanticContentAttribute = .forceRightToLeft