iphone - وورد - محاذاة النص في html
محاذاة النص والصورة على UIButton مع imageEdgeInsets و titleEdgeInsets (8)
أود وضع رمز على يسار سطرين من النص بحيث يكون هناك حوالي 2-3 بكسل من المساحة بين الصورة وبداية النص. عنصر التحكم نفسه هو مركز محاذاة أفقيًا (تم تعيينه من خلال واجهة منشئ)
سيشبه هذا الزر شيئًا كالتالي:
| |
|[Image] Add To |
| Favorites |
أحاول تكوين هذا مع contentEdgeInset و imageEdgeInsets و titleEdgeInsets دون جدوى. أتفهم أن القيمة السالبة توسع الحافة بينما تقللها القيمة الإيجابية لنقلها إلى المركز أقرب.
حاولت:
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, -image.size.width, 0, 0)];
[button setImageEdgeInsets:UIEdgeInsetsMake(0, button.titleLabel.bounds.size.width, 0, 0)];
لكن هذا لا يعرضها بشكل صحيح. لقد قمت بتعديل القيم لكن الانتقال من القول -5 إلى -10 على القيمة الداخلية اليسرى لا يبدو أنه يتحرك بطريقة متوقعة. -10 سوف يسحبون النص على طول الطريق إلى اليسار لذا كنت أتوقع -5 أن أسحره في منتصف الطريق من الجانب الأيسر لكنه لا.
ما هو المنطق وراء الدفاتر؟ لست على دراية بمواضع الصور والمصطلحات ذات الصلة.
لقد استخدمت سؤال SO كمرجع لكن شيئًا عن قيمي ليس صحيحًا. UIButton: كيفية توسيط صورة ونص باستخدام imageEdgeInsets و titleEdgeInsets؟
أنا متأخرة قليلا لهذا الحزب أيضا ، ولكن أعتقد أن لدي شيء مفيد لإضافة: س).
لقد أنشأت فئة فرعية من UIButton
الغرض منها هو أن يكون قادرا على اختيار مكان صورة الزر ، إما رأسيًا أو أفقيًا.
هذا يعني أنه يمكنك عمل هذا النوع من الأزرار:
هنا التفاصيل حول كيفية إنشاء هذه الأزرار مع صفي:
func makeButton (imageVerticalAlignment:LayoutableButton.VerticalAlignment, imageHorizontalAlignment:LayoutableButton.HorizontalAlignment, title:String) -> LayoutableButton {
let button = LayoutableButton ()
button.imageVerticalAlignment = imageVerticalAlignment
button.imageHorizontalAlignment = imageHorizontalAlignment
button.setTitle(title, for: .normal)
// add image, border, ...
return button
}
let button1 = makeButton(imageVerticalAlignment: .center, imageHorizontalAlignment: .left, title: "button1")
let button2 = makeButton(imageVerticalAlignment: .center, imageHorizontalAlignment: .right, title: "button2")
let button3 = makeButton(imageVerticalAlignment: .top, imageHorizontalAlignment: .center, title: "button3")
let button4 = makeButton(imageVerticalAlignment: .bottom, imageHorizontalAlignment: .center, title: "button4")
let button5 = makeButton(imageVerticalAlignment: .bottom, imageHorizontalAlignment: .center, title: "button5")
button5.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
ولإجراء ذلك ، أضفت 2 من السمات: imageVerticalAlignment
و imageHorizontalAlignment
. بالطبع ، إذا كان الزر الخاص بك يحتوي فقط على صورة أو عنوان ... لا تستخدم هذا الفصل على الإطلاق!
أضفت أيضًا سمة تسمى imageToTitleSpacing
والتي تسمح لك بتعديل المسافة بين العنوان والصورة.
يحاول هذا الفصل جهده ليكون متوافقًا إذا كنت تريد استخدام imageEdgeInsets
و titleEdgeInsets
و titleEdgeInsets
مباشرة أو في combinaison مع سمات التنسيق الجديدة.
كما يشرح لناravron ، أبذل قصارى جهدي لجعل حافة محتوى الزر صحيحة (كما ترون بالحدود الحمراء).
يمكنك أيضًا استخدامه في Interface Builder:
- إنشاء UIButton
- تغيير فئة الزر
- ضبط السمات القابلة للتنسيق باستخدام "center" أو "top" أو "bottom" أو "left" أو "right"
هنا الكود ( gist ):
@IBDesignable
class LayoutableButton: UIButton {
enum VerticalAlignment : String {
case center, top, bottom, unset
}
enum HorizontalAlignment : String {
case center, left, right, unset
}
@IBInspectable
var imageToTitleSpacing: CGFloat = 8.0 {
didSet {
setNeedsLayout()
}
}
var imageVerticalAlignment: VerticalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
var imageHorizontalAlignment: HorizontalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageVerticalAlignment' instead.")
@IBInspectable
var imageVerticalAlignmentName: String {
get {
return imageVerticalAlignment.rawValue
}
set {
if let value = VerticalAlignment(rawValue: newValue) {
imageVerticalAlignment = value
} else {
imageVerticalAlignment = .unset
}
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageHorizontalAlignment' instead.")
@IBInspectable
var imageHorizontalAlignmentName: String {
get {
return imageHorizontalAlignment.rawValue
}
set {
if let value = HorizontalAlignment(rawValue: newValue) {
imageHorizontalAlignment = value
} else {
imageHorizontalAlignment = .unset
}
}
}
var extraContentEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var contentEdgeInsets: UIEdgeInsets {
get {
return super.contentEdgeInsets
}
set {
super.contentEdgeInsets = newValue
self.extraContentEdgeInsets = newValue
}
}
var extraImageEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var imageEdgeInsets: UIEdgeInsets {
get {
return super.imageEdgeInsets
}
set {
super.imageEdgeInsets = newValue
self.extraImageEdgeInsets = newValue
}
}
var extraTitleEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var titleEdgeInsets: UIEdgeInsets {
get {
return super.titleEdgeInsets
}
set {
super.titleEdgeInsets = newValue
self.extraTitleEdgeInsets = newValue
}
}
//Needed to avoid IB crash during autolayout
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageEdgeInsets = super.imageEdgeInsets
self.titleEdgeInsets = super.titleEdgeInsets
self.contentEdgeInsets = super.contentEdgeInsets
}
override func layoutSubviews() {
if let imageSize = self.imageView?.image?.size,
let font = self.titleLabel?.font,
let textSize = self.titleLabel?.attributedText?.size() ?? self.titleLabel?.text?.size(attributes: [NSFontAttributeName: font]) {
var _imageEdgeInsets = UIEdgeInsets.zero
var _titleEdgeInsets = UIEdgeInsets.zero
var _contentEdgeInsets = UIEdgeInsets.zero
let halfImageToTitleSpacing = imageToTitleSpacing / 2.0
switch imageVerticalAlignment {
case .bottom:
_imageEdgeInsets.top = (textSize.height + imageToTitleSpacing) / 2.0
_imageEdgeInsets.bottom = (-textSize.height - imageToTitleSpacing) / 2.0
_titleEdgeInsets.top = (-imageSize.height - imageToTitleSpacing) / 2.0
_titleEdgeInsets.bottom = (imageSize.height + imageToTitleSpacing) / 2.0
_contentEdgeInsets.top = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
_contentEdgeInsets.bottom = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .top:
_imageEdgeInsets.top = (-textSize.height - imageToTitleSpacing) / 2.0
_imageEdgeInsets.bottom = (textSize.height + imageToTitleSpacing) / 2.0
_titleEdgeInsets.top = (imageSize.height + imageToTitleSpacing) / 2.0
_titleEdgeInsets.bottom = (-imageSize.height - imageToTitleSpacing) / 2.0
_contentEdgeInsets.top = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
_contentEdgeInsets.bottom = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .center:
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
break
case .unset:
break
}
switch imageHorizontalAlignment {
case .left:
_imageEdgeInsets.left = -halfImageToTitleSpacing
_imageEdgeInsets.right = halfImageToTitleSpacing
_titleEdgeInsets.left = halfImageToTitleSpacing
_titleEdgeInsets.right = -halfImageToTitleSpacing
_contentEdgeInsets.left = halfImageToTitleSpacing
_contentEdgeInsets.right = halfImageToTitleSpacing
case .right:
_imageEdgeInsets.left = textSize.width + halfImageToTitleSpacing
_imageEdgeInsets.right = -textSize.width - halfImageToTitleSpacing
_titleEdgeInsets.left = -imageSize.width - halfImageToTitleSpacing
_titleEdgeInsets.right = imageSize.width + halfImageToTitleSpacing
_contentEdgeInsets.left = halfImageToTitleSpacing
_contentEdgeInsets.right = halfImageToTitleSpacing
case .center:
_imageEdgeInsets.left = textSize.width / 2.0
_imageEdgeInsets.right = -textSize.width / 2.0
_titleEdgeInsets.left = -imageSize.width / 2.0
_titleEdgeInsets.right = imageSize.width / 2.0
_contentEdgeInsets.left = -((imageSize.width + textSize.width) - max (imageSize.width, textSize.width)) / 2.0
_contentEdgeInsets.right = -((imageSize.width + textSize.width) - max (imageSize.width, textSize.width)) / 2.0
case .unset:
break
}
_contentEdgeInsets.top += extraContentEdgeInsets.top
_contentEdgeInsets.bottom += extraContentEdgeInsets.bottom
_contentEdgeInsets.left += extraContentEdgeInsets.left
_contentEdgeInsets.right += extraContentEdgeInsets.right
_imageEdgeInsets.top += extraImageEdgeInsets.top
_imageEdgeInsets.bottom += extraImageEdgeInsets.bottom
_imageEdgeInsets.left += extraImageEdgeInsets.left
_imageEdgeInsets.right += extraImageEdgeInsets.right
_titleEdgeInsets.top += extraTitleEdgeInsets.top
_titleEdgeInsets.bottom += extraTitleEdgeInsets.bottom
_titleEdgeInsets.left += extraTitleEdgeInsets.left
_titleEdgeInsets.right += extraTitleEdgeInsets.right
super.imageEdgeInsets = _imageEdgeInsets
super.titleEdgeInsets = _titleEdgeInsets
super.contentEdgeInsets = _contentEdgeInsets
} else {
super.imageEdgeInsets = extraImageEdgeInsets
super.titleEdgeInsets = extraTitleEdgeInsets
super.contentEdgeInsets = extraContentEdgeInsets
}
super.layoutSubviews()
}
}
أنا متأخرة قليلاً لهذا الحزب ، لكن أعتقد أن لدي شيء مفيد لإضافته.
إجابة Kekoa رائعة ، ولكن كما يذكر RonLugge ، يمكن أن يجعل الزر لا يعد احترام sizeToFit
، أو الأهم من ذلك ، يمكن أن يسبب الزر sizeToFit
محتواه عندما يكون حجمه جوهريا. ييكيس!
أولا ، مع ذلك ،
شرح موجز عن كيفية عمل titleEdgeInsets
و titleEdgeInsets
:
تحتوي المستندات الخاصة بـ imageEdgeInsets
على ما يلي ، جزئيًا:
استخدم هذه الخاصية لتغيير حجم وإعادة وضع مستطيل الرسم الفعال لصورة الزر. يمكنك تحديد قيمة مختلفة لكل من الأشكال الأربعة (أعلى ، يسار ، أسفل ، يمين). تنكمش قيمة موجبة ، أو insets ، تلك الحافة — مما يجعلها أقرب إلى وسط الزر. تقوم قيمة سالبة بتوسيع هذه الحافة أو بداياتها.
أعتقد أن هذه الوثائق كتبت بتخيل أن الزر ليس له عنوان ، بل مجرد صورة. يجعل التفكير أكثر بهذه الطريقة ، ويتصرف كيفية UIEdgeInsets
عادةً. بشكل أساسي ، يتم نقل إطار الصورة (أو العنوان ، بالعنوان titleEdgeInsets
) إلى الداخل titleEdgeInsets
السلبية.
حسنا ، ماذا في ذلك؟
أنا أصل إلى هناك! إليك ما لديك بشكل افتراضي ، تعيين صورة وعنوان (حدود الزر باللون الأخضر فقط لإظهار مكانها):
عندما تريد التباعد بين الصورة والعنوان ، دون التسبب في أي سحق ، تحتاج إلى تعيين أربعة إدخالات مختلفة ، اثنان على كل من الصورة والعنوان. هذا لأنك لا ترغب في تغيير أحجام إطارات تلك العناصر ، ولكن فقط لوضعها. عندما تبدأ بالتفكير بهذه الطريقة ، يصبح التغيير المطلوب لفئة Kekoa الممتازة واضحا:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
}
@end
لكن انتظر ، قل ، عندما أفعل ذلك ، أحصل على هذا:
آه أجل! لقد نسيت ، لقد حذرتني المستندات من ذلك. يقولون ، في جزء منه:
يتم استخدام هذه الخاصية فقط لتحديد موقع الصورة أثناء التخطيط. لا يستخدم الزر هذه الخاصية لتحديد
intrinsicContentSize
وsizeThatFits:
ولكن هناك خاصية يمكن أن تساعد ، وهذا هو contentEdgeInsets
. المستندات لهذا القول ، في جزء منه:
يستخدم الزر هذه الخاصية لتحديد
intrinsicContentSize
وsizeThatFits:
هذا يبدو جيدا. لذلك دعونا نقوم بتعديل الفئة مرة أخرى:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
}
@end
وماذا تحصل؟
يبدو وكأنه الفائز لي.
العمل في سويفت ولا تريد القيام بأي تفكير على الإطلاق؟ إليك الإصدار النهائي من الإضافة في Swift:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
أيضا إذا كنت تريد أن تجعل شيء مماثل ل
انت تحتاج
1. ضبط المحاذاة الأفقية والعمودية للزر ل
البحث عن جميع القيم المطلوبة وتعيين
UIImageEdgeInsets
CGSize buttonSize = button.frame.size; NSString *buttonTitle = button.titleLabel.text; CGSize titleSize = [buttonTitle sizeWithAttributes:@{ NSFontAttributeName : [UIFont camFontZonaProBoldWithSize:12.f] }]; UIImage *buttonImage = button.imageView.image; CGSize buttonImageSize = buttonImage.size; CGFloat offsetBetweenImageAndText = 10; //vertical space between image and text [button setImageEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height + buttonImageSize.height)) / 2 - offsetBetweenImageAndText, (buttonSize.width - buttonImageSize.width) / 2, 0,0)]; [button setTitleEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height + buttonImageSize.height)) / 2 + buttonImageSize.height + offsetBetweenImageAndText, titleSize.width + [button imageEdgeInsets].left > buttonSize.width ? -buttonImage.size.width + (buttonSize.width - titleSize.width) / 2 : (buttonSize.width - titleSize.width) / 2 - buttonImage.size.width, 0,0)];
سيقوم هذا بترتيب العنوان والصورة على الزر.
كما يرجى ملاحظة تحديث هذا على كل relayout
سريع
import UIKit
extension UIButton {
// MARK: - UIButton+Aligment
func alignContentVerticallyByCenter(offset:CGFloat = 10) {
let buttonSize = frame.size
if let titleLabel = titleLabel,
let imageView = imageView {
if let buttonTitle = titleLabel.text,
let image = imageView.image {
let titleString:NSString = NSString(string: buttonTitle)
let titleSize = titleString.sizeWithAttributes([
NSFontAttributeName : titleLabel.font
])
let buttonImageSize = image.size
let topImageOffset = (buttonSize.height - (titleSize.height + buttonImageSize.height + offset)) / 2
let leftImageOffset = (buttonSize.width - buttonImageSize.width) / 2
imageEdgeInsets = UIEdgeInsetsMake(topImageOffset,
leftImageOffset,
0,0)
let titleTopOffset = topImageOffset + offset + buttonImageSize.height
let leftTitleOffset = (buttonSize.width - titleSize.width) / 2 - image.size.width
titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset,
leftTitleOffset,
0,0)
}
}
}
}
إضافة صغيرة إلى Riley Avron للإجابة على التغييرات في لغة الحساب:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let writingDirection = UIApplication.sharedApplication().userInterfaceLayoutDirection
let factor: CGFloat = writingDirection == .LeftToRight ? 1 : -1
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount*factor, bottom: 0, right: insetAmount*factor)
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount*factor, bottom: 0, right: -insetAmount*factor)
self.contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
في ما يلي مثال بسيط لكيفية استخدام imageEdgeInsets سيؤدي هذا إلى إنشاء زر 30x30 بمساحة أكبر بـ 10 بيكسلات على طول الطريق (50 × 50)
var expandHittableAreaAmt : CGFloat = 10
var buttonWidth : CGFloat = 30
var button = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
button.frame = CGRectMake(0, 0, buttonWidth+expandHittableAreaAmt, buttonWidth+expandHittableAreaAmt)
button.imageEdgeInsets = UIEdgeInsetsMake(expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt)
button.setImage(UIImage(named: "buttonImage"), forState: .Normal)
button.addTarget(self, action: "didTouchButton:", forControlEvents:.TouchUpInside)
يمكنك تجنب الكثير من المتاعب عن طريق استخدام هذا -
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
myButton.contentVerticalAlignment = UIControlContentVerticalAlignment;
سيؤدي هذا إلى محاذاة جميع المحتويات تلقائيًا إلى اليسار (أو أينما تريد)
سويفت 3:
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
myButton.contentVerticalAlignment = UIControlContentVerticalAlignment.center;
سويفت 4.x
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let writingDirection = UIApplication.shared.userInterfaceLayoutDirection
let factor: CGFloat = writingDirection == .leftToRight ? 1 : -1
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount*factor, bottom: 0, right: insetAmount*factor)
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount*factor, bottom: 0, right: -insetAmount*factor)
self.contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
الاستعمال :
button.centerTextAndImage(spacing: 10.0)