UIButton hört nicht auf die Einstellung des Inhaltsmodus?

91

firstButton ist ein UIButton vom Typ Custom. Ich platziere programmgesteuert drei davon in jeder Zelle einer Tabelle, also:

[firstButton setImage:markImage forState:UIControlStateNormal];
[firstButton setContentMode:UIViewContentModeScaleAspectFit];
[cell.contentView addSubview:firstButton];

An anderer Stelle sage ich es zu clipToBounds. Was ich bekomme, ist ein Ausschnitt des mittleren Quadrats des Bildes und keine aspektskalierte Darstellung. Ich habe dies auf viele Arten versucht, einschließlich des Festlegens der mode-Eigenschaft in firstButton.imageView, was ebenfalls nicht zu funktionieren scheint.

Dan Ray
quelle
1
Siehe Lösung von Chris Nolet unten: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
Siehe stackoverflow.com/a/28205566/481207, aus dem hervorgeht, dass für UIViewContentModeScaleAspectFit sowohl die Einstellung contentVerticalAlignment als auch contentHorizontalAlignment erforderlich ist.
Matt

Antworten:

186

Ich hatte das gleiche Problem. Ich sehe, dass diese Frage etwas alt ist, aber ich möchte eine klare und korrekte Antwort geben, um anderen Leuten (wie mir) einige Zeit zu ersparen, wenn sie in ihren Suchergebnissen auftaucht.

Ich musste ein bisschen suchen und experimentieren, aber ich fand die Lösung. Stellen Sie einfach den ContentMode der "versteckten" ImageView ein, die sich im UIButton befindet.

[[firstButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[firstButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];

Vielleicht hat Dan Ray in seiner akzeptierten Antwort darauf angespielt, aber ich vermute nicht.

Dave
quelle
1
Nein, das war es nicht. Die Lösung, für die ich mich entschieden habe, bestand darin, ein UIImageView zu verwenden, um das Bild zu halten, und dann einen klaren, transparenten UIButton vom Typ "custom" darüber.
Dan Ray
Dave, zumindest unter iOS 3.2 scheint Ihre Lösung für mich nicht zu funktionieren. Schade, denn ich hatte gehofft, die Hervorhebung des Bildes durch Klicken auf "kostenlos" zu erhalten. Ich habe sogar sichergestellt, dass button.imageView nicht gleich Null ist, wo ich contentMode eingestellt habe, und das Bild nach dem Festlegen von contentMode festgelegt, genau wie Sie es tun.
Jacques
2
Nur um zu verdeutlichen, bedeutet "funktioniert nicht", dass "das Bild in seiner vollen Auflösung angezeigt wird und nicht wie erhofft verkleinert wird".
Jacques
Jacques, das oben genannte funktioniert für mich in iOS 4.x. Leider kann ich das Problem "Größe wird nicht geändert" beim Erstellen mit einem v3.2-Ziel reproduzieren. Ich habe versucht, die Rahmengröße der UIButton-Ansicht zu ändern, aber das schien auch nicht zu helfen. Pfui.
Dave
4
Siehe Lösung von Chris Nolet unten: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
73

Wenn Sie sich mit dem Bild des UIButton befassen (im Gegensatz zu seinem Hintergrundbild), hat das Festlegen des contentMode auf dem UIButton selbst oder auf seiner imageView keine Auswirkung (trotz der Aussagen anderer Antworten).

Alternativ können Sie dies stattdessen tun:

self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Oder passen Sie Ihr Bild entsprechend an.

ODER verwenden Sie einfach eine UIImageView (die den ContentMode ordnungsgemäß berücksichtigt) mit einem daran angehängten UITapGestureRecognizer oder einen transparenten UIButton darüber.

Alfie Hanssen
quelle
4
Dies funktioniert für meinen Fall in iOS 7, während dies bei allen anderen hier nicht der Fall ist.
Byte
5
Das Festlegen von contentHorizontalAlignment und contentVerticalAlignment ist die richtige Lösung. Eine Erklärung finden Sie unter stackoverflow.com/a/28205566/481207 .
Matt
1
Dies ist die Antwort, nach der ich gesucht habe.
Ninjaneer
4
Diese Antwort ist falsch. Sie tun festlegen müssen contentModeauf die , imageViewwenn Sie irgendeine Art von Aspekt Füllung oder fit machen wollen, wie andere Antworten geklärt haben. Siehe: stackoverflow.com/a/7944316/746890 .
Chris Nolet
49

Anstatt die Einstellung contentModeauf der Schaltfläche selbst, die Sie einstellen möchten werden contentHorizontalAlignmentund contentVerticalAlignmentEigenschaften und (entscheidend) die contentModefür die Schaltfläche imageViewfür jede Art von Aspekte Füllung oder Passform. Hier ist ein Beispiel:

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

Natürlich können Sie auch andere Dinge tun, z. B. das Bild der Schaltfläche am oberen Rand der Schaltfläche ausrichten. Wenn Sie keine Seitenfüllung oder -anpassung benötigen, können Sie die Ausrichtung einfach selbst festlegen:

button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

In Swift möchten Sie Folgendes verwenden:

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

Dies funktioniert für alle Versionen von iOS, einschließlich der neuesten Versionen mit automatischem Layout (dh iOS 4 bis iOS 11+).

Chris Nolet
quelle
2
Vielen Dank, Chris - das hat mein Problem gelöst, oder besser gesagt, in Kombination mit contentEdgeInsets, um mein Bild ein wenig von der Oberkante zu entfernen.
Rob Reuss
7

Nach ein paar Stunden der Verwirrung habe ich es unter iOS 3.2 zum Laufen gebracht. Wie bereits erwähnt, hat die Verwendung von setBackgroundImage anstelle von setImage die Aufgabe für mich erledigt.

CGRect myButtonFrame = CGRectMake(0, 0, 250, 250);
UIImage *myButtonImage = [UIImage imageNamed:@"buttonImage"];

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];

[myButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
[myButton setFrame: myButtonFrame];
[myButton setContentMode: UIViewContentModeScaleAspectFit];
Pierre
quelle
6

Die Antwort besteht darin, ein UIImageView mit allen gewünschten Einstellungen für den Inhaltsmodus zu verwenden und dann eine benutzerdefinierte Schaltfläche darüber zu legen. Dumm, dass man das nicht alles auf einmal machen kann, aber es scheint, dass man das nicht kann.

Dan Ray
quelle
4

Habe eine Lösung dafür gefunden. Setzen Sie die adjustsImageWhenHighlightedEigenschaft von UIButtonauf NO.

  UIButton *b = [[UIButton alloc] initWithFrame:rect];
        [b setImage:image forState:UIControlStateNormal];
        [b.imageView setContentMode:UIViewContentModeScaleAspectFill];
        [b setAdjustsImageWhenHighlighted:NO];

Hoffe das hilft. Fühlen Sie sich frei, unten zu kommentieren, ich werde alle Ihre Fragen beantworten.

iOSDevSF
quelle
Dies ist die perfekte Lösung.
Gaurav
Funktioniert nicht Dies verhindert lediglich, dass die Schaltfläche hervorgehoben wird.
Matt
4

Meine Antwort ähnelt der von Kuba. Ich musste mein Bild programmgesteuert einstellen.

UIImage *image = [[UIImage alloc] initWithContentsOfFile:...];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill; //this is needed for some reason, won't work without it.
for(UIView *view in button.subviews) {
    view.contentMode = UIViewContentModeScaleAspectFill;
}
Ninjaneer
quelle
3

Einzige Lösung, die bei mir funktioniert hat:

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Tariq
quelle
3

Swift 3

self.firstButton.imageView?.contentMode = .scaleAspectFill
Vaibhav Saran
quelle
1

Versuchen Sie statt setImage setBackgroundImage

Dämmerung
quelle
3
Hmp. A, das ist dumm, es sollte die Einstellung INHALTSMODUS für seinen INHALT respektieren, oder? Und B, es scheint immer noch nicht die Moduseinstellung zu respektieren - es ist jetzt auf "Stretch" (was in diesem Fall eher "Squeeze" ist) gesperrt und skaliert den Inhalt nicht in Bezug auf seinen Aspekt Verhältnis.
Dan Ray
1

Ich glaube, wir haben hier ein einfaches Problem mit dem Interface Builder - anscheinend ignoriert der IB alle Änderungen im Inhaltsmodus, nachdem Sie die Bildeigenschaft festgelegt haben.

Die Lösung ist so einfach: Stellen Sie den Inhaltsmodus ein, entfernen Sie zuvor festgelegte Bildnamen (stellen Sie sicher, dass Sie sie in allen Zuständen entfernen, Standard, hervorgehoben usw.), und geben Sie dann die gewünschten Bildnamen in allen gewünschten Zuständen erneut ein - et voilà .

JohnPayne
quelle
1
Das gleiche gilt für das programmgesteuerte Einstellen des Inhaltsmodus - stellen Sie das Bild nicht ein,
bevor Sie
0

Ich empfehle auch, einen Blick auf die adjustsImageWhenHighlighted UIButtonEigenschaft zu werfen , um seltsame Verformungen des Bildes zu vermeiden, wenn die Taste gedrückt wird.

MonsieurDart
quelle
0

Als ich versuchte, dies herauszufinden, wurde meine Methode im Laufe der Zeit etwas hackiger, und ich landete in der Unterklasse UIButton und überschrieb setHighlighted:

Für mich funktioniert es, das Bild Alpha einfach auf 0,5 zu reduzieren, da es sich auf einem schwarzen Hintergrund befindet.

Es funktioniert jedoch nur, wenn ich [super setHighlighted:] auskommentiere (wo es scheint, dass der bilddehnungsfähige Code läuft), was einfach nicht der richtige Weg ist, dies überhaupt zu lösen ... alles scheint zu sein funktioniert aber gut. Wir werden sehen, wie es funktioniert, wenn ich weiter daran arbeite.

- (void)setHighlighted:(BOOL)highlight {
    if (highlight) {
        [self.imageView setAlpha:.5];
    }  else {
        [self.imageView setAlpha:1];        
    }

//    [super setHighlighted:highlight];
}
Jankins
quelle
1
Für den Fall, dass jemand dies für relevant hält, schien meine obige Methode in Ordnung zu sein, bis ich die Schaltflächen in eine UIScrollView einfügte, in der manchmal das Highlight der Schaltfläche "hängen blieb", was ich vermutete, dass es irgendwann passieren könnte.
Jankins
0

Wenn jemand nach einer Antwort sucht, die in iOS 6 und iOS 7 und im Storyboard funktioniert:

Sie können ein Bild in Ihrem Storyboard festlegen:

Geben Sie hier die Bildbeschreibung ein

Und dann:

for(UIView* testId in self.subviews) {
    if([testId isKindOfClass:[UIImageView class]])
        [testId setContentMode:UIViewContentModeScaleAspectFill];
}
Jakub
quelle
0

Wenn der UIButton die Einstellungen für Layoutbeschränkungen nicht zu hören scheint, überprüfen Sie, ob die Bilder größer als die Schaltflächengröße sind. Verwenden Sie für Retina-Auflösungen immer die Bilder @ 2x und @ 3x.

Totoro
quelle
0

Diese beiden Dinge (die anfangs ziemlich schwer zu finden sind) dehnen Ihr UIButton-Bild auf die Größe der Schaltfläche:

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

man sollte immer versuchen, solche im Storyboard anstatt im Code festzulegen.

delta2flat
quelle