ios uicontrol - iPhone UIButton-posizione dell'immagine




view label (12)

Su iOS 9 in poi, sembra che un modo semplice per raggiungere questo obiettivo sia forzare la semantica della vista.

O programmaticamente, usando:

button.semanticContentAttribute = .ForceRightToLeft

Ho un UIButton con il testo "Esplora l'app" e UIImage (>) In Interface Builder assomiglia a:

[ (>) Explore the app ]

Ma ho bisogno di mettere questa UIImage DOPO il testo:

[ Explore the app (>) ]

Come posso spostare la UIImage a destra?


Forzare "da destra a sinistra" per il pulsante non è un'opzione se la tua app supporta sia "da sinistra a destra" sia da "da destra a sinistra".

La soluzione che ha funzionato per me è una sottoclasse che può essere aggiunta al pulsante nello Storyboard e funziona bene con i vincoli (testati in 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)
        }

    }

}

Dove 'padding' sarebbe lo spazio tra il titolo e l'immagine.


Impostare imageEdgeInset e titleEdgeInset per spostare i componenti all'interno dell'immagine. È anche possibile creare un pulsante utilizzando tali elementi grafici di dimensioni complete e utilizzarli come immagine di sfondo per il pulsante (quindi utilizzare titleEdgeInsets per spostare il titolo attorno).


La risposta di Raymond W è la migliore qui. Sottoclasse UIButton con layout personalizzati. Estremamente semplice da fare, ecco un'impaginazione di layout che ha funzionato per me:

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

Basandosi su risposte precedenti. Se si desidera avere un margine tra l'icona e il titolo del pulsante, il codice deve cambiare leggermente per evitare di fluttuare dell'etichetta e dell'icona sopra i limiti dei pulsanti di dimensioni intrinseche.

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)

L'ultima riga di codice è importante per il calcolo della dimensione intrinseca del contenuto per il layout automatico.


Costruire la risposta con @split ...

La risposta è fantastica, ma ignora il fatto che il pulsante può avere immagini personalizzate e margini del bordo del titolo impostati in precedenza (ad esempio nello storyboard).

Ad esempio, è possibile che l'immagine abbia un riempimento nella parte superiore e inferiore del contenitore, ma spostare l'immagine sul lato destro del pulsante.

Ho esteso il concetto con questo metodo: -

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

Questo crea un pulsante allineato a destra, in questo modo:

[           button label (>)]

Il pulsante non regola la sua larghezza in base al contesto, quindi lo spazio apparirà a sinistra dell'etichetta. Puoi risolvere questo problema calcolando la larghezza del frame del pulsante da buttonLabelSize.width e dal pulsanteImageSize.width.


button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

La mia soluzione a questo è abbastanza semplice

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

Questa soluzione funziona con iOS 7 e versioni successive

Basta sottoclasse 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

Uso (da qualche parte nella tua classe):

[self.myButton setTitle:@"Any text" forState:UIControlStateNormal];
[self.myButton swapTextWithImage];

In rapido:

override func layoutSubviews()
{
    super.layoutSubviews()

    var imageFrame = self.imageView?.frame;
    var labelFrame = self.titleLabel?.frame;

    let inset: CGFloat = 5

    if var imageFrame = imageFrame
    {
        if var labelFrame = labelFrame
        {
            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
        }
    }
}

basta cambiare la configurazione di stato per disabilitare e scegliere quello che vuoi, immagine di sfondo per stato disabilitato





ios iphone cocoa-touch uibutton imageedgeinsets