У мене є 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
для переміщення заголовка навколо).
Відповідь Реймонда У найкраще тут. Підклас UIButton з користувацьким layoutSubviews. Це надзвичайно просто, ось реалізація layoutSubviews, яка працювала для мене:
- (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
вже враховується за допомогою супер.
Примушувати кнопку "справа наліво" для кнопки - це не варіант, якщо ваш додаток підтримує і "зліва направо", і "справа наліво".
Для мене працювало рішення - підклас, який можна додати до кнопки на дошці розкадрувань і добре працює з обмеженнями (перевірено в 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
.
У Свіфті:
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 (>)]
Кнопка не регулює її ширину відповідно до контексту, тому пробіл з’явиться зліва від мітки. Ви можете вирішити це шляхом обчислення ширини рамки кнопки від кнопкиLabelSize.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