ridimensionare l'immagine in un pulsante UIB per AspectFit?


94

Voglio aggiungere un'immagine a un UIButton e voglio anche ridimensionare la mia immagine per adattarla al UIButton (rimpicciolire l'immagine). Per favore mostrami come farlo.

Questo è quello che ho provato, ma non funziona:

  • Aggiunta di un'immagine al pulsante e utilizzo di setContentMode:
[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
  • Creazione di una "immagine allungata":
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

Penso che questo sia stato modificato per essere il comportamento predefinito nel firmware 4.0 e versioni successive.
Shaun Budhram

1
Vedi stackoverflow.com/a/28205566/481207 per la soluzione.
Matt

Risposte:


28

Se vuoi davvero ridimensionare un'immagine, fallo, ma dovresti ridimensionarla prima di usarla. Il ridimensionamento in fase di esecuzione perderà solo i cicli della CPU.

Questa è la categoria che sto usando per ridimensionare un'immagine:

UIImage + Extra.h

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

UIImage + Extra.m

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

UIImage *sourceImage = self;
UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
                scaleFactor = widthFactor;
        else
                scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
}


// this is actually the interesting part:

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width  = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;
}

@end

Puoi usarlo nella dimensione che desideri. Piace :

[self.itemImageButton setImage:[stretchImage imageByScalingProportionallyToSize:CGSizeMake(20,20)]];

Grazie per la tua risposta, Gcamp. Avevo un metodo per ridimensionare in base al rapporto. Ma cerco ancora di trovare un modo per dire a UIButton di farlo per me. La mia immagine viene caricata da Internet, quindi non posso ridimensionarla in fase di compilazione. BTW, grazie mille per la tua risposta.
KONG

2
Poiché l'immagine viene inserita in un CALayer, resa e memorizzata nella cache da Quartz, le prestazioni non dovrebbero essere peggiori se la si inserisce a grandezza naturale. Ad ogni modo, stai ridimensionando ~ 1 volta. La risposta di gcamp è molto più importante se ridimensiona costantemente il pulsante o fai altre cose che farebbero scattare Quartz per ridisegnare il livello dell'immagine.
Ben Gotow

sembra che la qualità dell'immagine sia ridotta. sto testando su iphone 6 plus. È vero? Ho anche un'immagine 3x.
Khant Thu Linn

Sì, questo codice è piuttosto vecchio. E 'stato UIGraphicsBeginImageContextinvece di UIGraphicsBeginImageContextWithOptions. L'ho appena risolto.
gcamp

sì, ma in molti casi non importa se perdi qualche ciclo, quindi non ha senso riempire il montone
Radu Simionescu

203

Ho avuto lo stesso problema. Basta impostare il ContentMode di ImageView che si trova all'interno del UIButton.

[[self.itemImageButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[self.itemImageButton setImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal];

Spero che questo ti aiuti.


14
Assicurati di impostare il file imageView . Inoltre non ho notato, per un po ', che stavo ancora usando backgroundImageView e non funzionava per quello.
Alexandre Gomes

2
Sembra che questo metodo abbia dei problemi quando lo stato del pulsante è "evidenziato". L'immagine tornerà alla modalità di riempimento. Qualche idea?
Yuanfei Zhu

Non funziona per me. Tuttavia, lo faccio funzionare usando [self.itemImageButton setbackgroundImage: [UIImage imageNamed: stretchImage] forState: UIControlStateNormal];
Mickey

3
Questo ha funzionato per me. Ho impostato la modalità contenuto come sopra. Tuttavia, è anche necessario impostare la stessa immagine dello stato evidenziato per evitare che l'immagine torni in "modalità riempimento". Ad esempio, [imageButton setImage: image forState: UIControlStateHighlighted];
Christopher,

1
Puoi farlo in Interface Builder con percorso chiave imageView.contentMode, tipo Numbere valore1
bendytree

107

Nessuna delle risposte qui ha funzionato davvero per me, ho risolto il problema con il seguente codice:

button.contentMode = UIViewContentModeScaleToFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Puoi farlo anche in Interface Builder.

inserisci qui la descrizione dell'immagine


5
Questo non ti dà un comportamento in forma come richiesto dall'OP.
Ortwin Gentz

3
@OrtwinGentz ​​puoi selezionare la modalità e impostare Aspect fitinvece di scale to fill.
Daniel

55

Il modo più semplice per impostare a livello di codice un'immagine UIButton in modalità adattamento aspetto :

Swift

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

Obiettivo-C

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

Nota: puoi modificare .scaleAspectFit (UIViewContentModeScaleAspectFit) in .scaleAspectFill (UIViewContentModeScaleAspectFill) per impostare una modalità di riempimento proporzionale


20

Ho avuto problemi con l'immagine che non si ridimensionava proporzionalmente, quindi il modo in cui l'ho risolta era usando gli inserti sui bordi.

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

16

Questo ora può essere fatto tramite le proprietà UIButton di IB. La chiave è impostare la tua immagine come sfondo, altrimenti non funzionerà.

inserisci qui la descrizione dell'immagine


14

Espandendo la risposta di Dave, puoi impostare il tutto contentModedel pulsante imageViewin IB, senza alcun codice, utilizzando gli attributi di runtime:

inserisci qui la descrizione dell'immagine

  • 1significa UIViewContentModeScaleAspectFit,
  • 2significherebbe UIViewContentModeScaleAspectFill.

8

Se desideri semplicemente ridurre l'immagine del pulsante:

yourButton.contentMode = UIViewContentModeScaleAspectFit;
yourButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

Dovrebbe essere yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
sdsykes

Non ho provato con .imageView. Funziona senza abbastanza bene.
Tulleb

5

1 - cancella il testo predefinito del pulsante (importante)

2 - imposta l'allineamento come l'immagine

3 - imposta la modalità contenuto come immagine

inserisci qui la descrizione dell'immagine


Bella risposta fratello ... mi ha aiutato molto. Grazie!
BharathRao

5

Ho un metodo che lo fa per me. Il metodo prende UIButtone adatta l'aspetto dell'immagine.

-(void)makeImageAspectFitForButton:(UIButton*)button{
    button.imageView.contentMode=UIViewContentModeScaleAspectFit;
    button.contentHorizontalAlignment=UIControlContentHorizontalAlignmentFill;
    button.contentVerticalAlignment=UIControlContentVerticalAlignmentFill;
}

4

La soluzione più pulita è utilizzare il layout automatico . Ho abbassato la priorità di resistenza alla compressione dei contenutiUIButton e ho impostato l'immagine (non l'immagine di sfondo ) tramite Interface Builder . Successivamente ho aggiunto un paio di vincoli che definiscono le dimensioni del mio pulsante (piuttosto complesso nel mio caso) e ha funzionato a meraviglia.


Questo ha funzionato per me, ma solo se ho scelto di utilizzare "Immagine di sfondo", non l'immagine effettiva. Basta che funzioni! Questo mi stava facendo impazzire.
Andy

Sotto Xcode 6.2 questo ha funzionato per me, ma come ha detto @AndrewHeinlein, usatoBackground Image
RoLYroLLs

3

assicurati di aver impostato l'immagine sulla proprietà Image, ma non sullo sfondo


2

L'immagine di sfondo può effettivamente essere impostata per ridimensionare il riempimento proporzionale abbastanza facilmente. Ho solo bisogno di fare qualcosa di simile in una sottoclasse di UIButton:

- (CGRect)backgroundRectForBounds:(CGRect)bounds
{
    // you'll need the original size of the image, you 
    // can save it from setBackgroundImage:forControlState
    return CGRectFitToFillRect(__original_image_frame_size__, bounds);
}

// Utility function, can be saved elsewhere
CGRect CGRectFitToFillRect( CGRect inRect, CGRect maxRect )
{
    CGFloat origRes = inRect.size.width / inRect.size.height;
    CGFloat newRes = maxRect.size.width / maxRect.size.height;

    CGRect retRect = maxRect;

    if (newRes < origRes)
    {
        retRect.size.width = inRect.size.width * maxRect.size.height / inRect.size.height;
        retRect.origin.x = roundf((maxRect.size.width - retRect.size.width) / 2);
    }
    else
    {
        retRect.size.height = inRect.size.height * maxRect.size.width / inRect.size.width;
        retRect.origin.y = roundf((maxRect.size.height - retRect.size.height) / 2);
    }

    return retRect;
}

Non è possibile senza una sottoclasse?
Iulian Onofrei

Questa risposta era specifica per backgroundImage. Per l'immagine principale puoi eseguire la scimmia con i file imageEdgeInsets.
Andy Poes

Lo so, e volevo se fosse possibile ottenere questo risultato senza una sottoclasse.
Iulian Onofrei

Per quanto ne so, non è possibile regolare l'immagine di sfondo senza sottoclassi.
Andy Poes

1

Swift 5.0

 myButton2.contentMode = .scaleAspectFit
 myButton2.contentHorizontalAlignment = .fill
 myButton2.contentVerticalAlignment = .fill

0

Per Xamarin.iOS (C #):

    myButton.VerticalAlignment = UIControlContentVerticalAlignment.Fill;
    myButton.HorizontalAlignment = UIControlContentHorizontalAlignment.Fill;
    myButton.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

-1

Hai solo bisogno di impostare la modalità del contenuto di UIButton imageview per tre eventi. -

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateNormal];

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateHighlighted];

[cell.imgIcon setImage:[UIImage imageWithData:data] forState:UIControlStateSelected];

Abbiamo il codice per tre eventi bcoz durante l'evidenziazione o la selezione se la dimensione del pulsante è QUADRATO e la dimensione dell'immagine è rettangolare, quindi mostrerà l'immagine quadrata al momento dell'evidenziazione o della selezione.

Sono sicuro che funzionerà per te.


Non stai impostando una modalità di contenuto, stai impostando l'immagine. E non sono eventi, sono stati. Stai facendo un gran casino. Questo è totalmente estraneo alla domanda.
manecosta
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.