UIButton wechselt nicht zu Aspect Fit im iPhone


105

Ich habe ein paar UIButtons und in IB sind sie auf Aspect Fit eingestellt, aber aus irgendeinem Grund dehnen sie sich immer. Gibt es noch etwas, das Sie einstellen müssen? Ich habe all die verschiedenen Ansichtsmodi ausprobiert und keiner von ihnen funktioniert, sie dehnen sich alle.


@Werner Altesischers Antwort ist die richtige. Nehmen Sie die entsprechenden Änderungen vor.
Harshit Gupta

1
@marty Stellen Sie Hintergrundbild oder Bild ein? Hintergrundbild unterstützt es nicht, nur Bild.
Juan Boero

Antworten:


45

Ich hatte dieses Problem schon einmal. Ich habe es gelöst, indem ich mein Bild in ein Feld eingefügt habe, in UIImageViewdem die contentModeEinstellungen tatsächlich funktionieren, und darüber ein transparentes benutzerdefiniertes UIButtonElement eingefügt habe.

EDIT: Diese Antwort ist veraltet. Siehe @Werner Altewischer Antwort für die richtige Antwort in modernen Versionen von iOS.


Ja, das habe ich versucht, aber jetzt kann ich den Knopf nicht bekommen, um das Bild wieder
anzubringen

Wie verwalten Sie Schaltflächenzustände mit dieser Technik? Es scheint ein Albtraum zu sein, auf Benutzerinteraktionen wie "hervorgehoben" zu reagieren.
SooDesuNe

3
Dies war vielleicht vor 2,5 Jahren der richtige Weg, als diese Frage beantwortet wurde. Jetzt können Sie die interne ImageView des UIButton bearbeiten und dort den Inhaltsmodus einstellen. Siehe die Antwort von @Werner Altewischer
Steve Haley

232

Die Lösung besteht darin, contentModedie imageViewEigenschaft auf die zu setzen UIButton. Das UIButtonmuss mit einem benutzerdefinierten Typ erstellt werden, damit dies funktioniert, glaube ich (andernfalls nilwird es für diese Eigenschaft zurückgegeben).


67
Dies funktionierte für mich:[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
Ayreguitar

2
Dies funktioniert auch bei mir, aber wenn ich adjustsImageWhenHighlighted = YES einstelle, wird das Bild erneut gedehnt, wenn ich auf die Schaltfläche tippe.
Cduck

1
Die Dehnung in adjustsImage wurde in iOS 6 beseitigt.
Ben Flynn

3
In iOS 8 funktioniert das bei mir eigentlich nicht. Die ursprüngliche Antwort (mit Platzieren einer Bildansicht hinter einer transparenten Schaltfläche) funktioniert am besten.
user1416564

3
in Swift du Jour:button.imageView!.contentMode = UIViewContentMode.scaleAspectFit
Nestor

57

Diese Methode hat bei mir sehr gut funktioniert.:

Wählen Sie in Xib die Schaltfläche und stellen Sie Folgendes ein user defined runtime attributes:

  • Schlüsselpfad: self.imageView.contentMode
  • Art: Number
  • Wert: 1

Klicken Sie hier, um die Lösung klarer zu sehen

Wir verwenden die Nummer, weil Sie dort keine Aufzählung verwenden können. UIViewContentModeScaleAspectFit ist jedoch gleich 1.


2
Dadurch wurde auch das Image im Interface Builder während der Entwurfszeit aktualisiert. Tolle Lösung.
George Filippakos

Tolle Lösung, wenig Code und funktioniert wie ein Zauber. Die Aufzählung basiert auf Listenelementen im Inhaltsmodus.
Kross

Sie können auch eine Erweiterung hinzufügen, um es ein bisschen einfacher zu machen: extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } }
Yonat

Ohne 'Selbst' imageView.contentModefür mich gearbeitet!
Jeevan

22

Wenn Sie dies in Interface Builder tun, können Sie den Inspektor für Laufzeitattribute verwenden, um dies direkt ohne Code festzulegen.

Stellen Sie Ihren Schlüsselpfad auf der Schaltfläche auf "imageView.contentMode" mit dem Typ "Number" und dem Wert "1" (oder einem beliebigen Modus) ein.

imageview.contentMode = 1


14

Verwenden Sie die imageView der Schaltfläche für den ContentMode. Nicht direkt auf der Schaltfläche selbst.

homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];

6

Wenn Sie das Bild UIImageViewhinter der Schaltfläche platzieren, verlieren Sie die integrierte Funktionalität der UIButtonKlasse, wie z. B. adjustsImageWhenHighlightedund adjustsImageWhenDisabled, und natürlich die Möglichkeit, verschiedene Bilder für verschiedene Zustände festzulegen (ohne dies selbst zu tun).

Wenn ein Bild für alle Kontrollzustände nicht gestreckt werden soll, besteht ein Ansatz darin, das Bild imageWithCGImage:scale:orientationwie in der folgenden Methode zu verwenden:

- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {

    // Check which dimension (width or height) to pay respect to and
    // calculate the scale factor
    CGFloat imgRatio = img.size.width / img.size.height, 
            btnRatio = btn.frame.size.width / btn.frame.size.height,
            scaleFactor = (imgRatio > btnRatio 
                           ? img.size.width / btn.frame.size.width
                           : img.size.height / btn.frame.size.height;

    // Create image using scale factor
    UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
                                             scale:scaleFactor
                                       orientation:UIImageOrientationUp];
    return scaledImg;
}

Um dies umzusetzen, würden wir schreiben:

UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];

Dies sollte verhindern, dass sich das Bild in allen Kontrollzuständen dehnt. Es hat bei mir funktioniert, aber lassen Sie es mich wissen, wenn es nicht funktioniert!

HINWEIS: Hier sprechen wir ein Problem an UIButton, das insideButton:sich insideView:auf das Bild bezieht , aber das könnte genauso gut sein oder was auch immer.


6

Ich hatte dieses Problem vor einiger Zeit. Das Problem, das ich hatte, war, dass ich versucht habe, diesen Effekt auf den Hintergrund-UIButton anzuwenden, der begrenzt ist und daher bedeutet, dass Sie ihn nicht so einfach anpassen können.

Der Trick besteht darin, es nur als Bild festzulegen und dann die Technik von @ ayreguitar anzuwenden, und das sollte es beheben!

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];

4

Das hat bei mir funktioniert

[button.imageView setContentMode:UIViewContentModeScaleAspectFit];

Vielen Dank an @ayreguitar für seinen Kommentar


4

Hier ist eine alternative Antwort in Kürze:

myButton.imageView?.contentMode = .ScaleAspectFit

4

Kombinieren Sie einige unterschiedliche Antworten zu einer Lösung: Erstellen Sie eine Schaltfläche mit einem benutzerdefinierten Typ, legen Sie die imageView contentMode-Eigenschaft der Schaltfläche fest und legen Sie das Bild für die Schaltfläche fest (nicht das Hintergrundbild, das weiterhin zum Füllen skaliert wird).

//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)

3
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;

Während dieses Code-Snippet die Frage lösen kann, hilft eine Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen. - Aus der Bewertung
Ferrybig

2

Diese Antwort basiert auf der Antwort von @ WernerAltewischer .

Um zu vermeiden, dass meine Schaltfläche mit einem IBOutlet verbunden wird, um den Code darauf auszuführen, habe ich die Klasse von UIButton in Unterklassen unterteilt:

// .h
@interface UIButtonWithImageAspectFit : UIButton
@end

// .m
@implementation UIButtonWithImageAspectFit

- (void) awakeFromNib {
    [self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}

@end



Erstellen Sie nun eine benutzerdefinierte Schaltfläche in Ihrer xib und legen Sie deren Bild fest (nicht das Hintergrundbild):

UIButtonWithImageAspectFit: Bild erstellen und festlegen


Stellen Sie dann die Klasse ein:

UIButtonWithImageAspectFit: Benutzerdefinierte Klasse festlegen

Du bist fertig!
Anstelle des
UIButton ohne Bildaspektanpassung
Bildaspekts Ihrer Schaltfläche ist jetzt die Anpassung wie erwartet:
UIButton mit Bildaspektanpassung


2

ios 12. Sie müssen auch die Inhaltsausrichtung hinzufügen

class FitButton: UIButton {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)


    }

    override func layoutSubviews() {
        self.imageView?.contentMode = .scaleAspectFill
        self.contentHorizontalAlignment = .fill
        self.contentVerticalAlignment = .fill
        super.layoutSubviews()


    }

}

1

Ich hatte Probleme damit, dass die Größe des Bilds nicht proportional geändert wurde, sodass bei der Art und Weise, wie ich es reparierte, Kanteneinsätze verwendet wurden.

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

1

Die UIView-Inhaltsmodi gelten für den "Inhalt" des entsprechenden CALayer. Dies funktioniert für UIImageViews, da sie den CALayerInhalt auf den entsprechenden Wert setzen CGImage.

drawRect: letztendlich wird auf den Ebeneninhalt gerendert.

Ein Benutzerdefinierter UIButton(soweit ich weiß) hat keinen Inhalt (die Schaltflächen im abgerundeten Rechteckstil werden möglicherweise mit Inhalt gerendert). Die Schaltfläche verfügt über Unteransichten: den Hintergrund UIImageView, das Bild UIImageViewund den Titel UILabel. Das Festlegen der contentModeUnteransichten kann das tun, was Sie wollen, aber das Herumspielen mit der UIButtonAnsichtshierarchie ist ein bisschen ein Nein-Nein.


1

Ändern UIButton.imageView.contentModehat bei mir nicht funktioniert.
Ich habe das Problem gelöst, indem ich das Bild auf die Eigenschaft 'Hintergrund' gesetzt habe.
Sie können bei Bedarf eine Verhältnisbeschränkung hinzufügen


1

Dies überschneidet sich mit vielen anderen Antworten, aber die Lösung für mich war zu

  • des Set contentModedes UIImageViewfür die Schaltfläche .ScaleAspectFit- , die entweder in den im Interface Builder „User Runtime - Attribut definiert“ durchgeführt werden (dh. self.imageView.contentMode, Zahl, 1) oder in einer UIButtonUnterklasse;
  • deaktivieren Sie "Autoresize Subviews";
  • Setzen Sie "Edge" auf "Image" und die entsprechenden Werte für "Top" und "Bottom" für "Inset" (die möglicherweise nur benötigt werden, wenn Sie wie ich ein PDF als Bild verwendet haben).

0

Sie können imageWithCGImage wie oben gezeigt verwenden (jedoch ohne die fehlenden Klammern).

Außerdem ... funktionieren Millionen von Nicht-4.0-Telefonen überhaupt nicht mit diesem Code.



0

Ähnlich wie bei @Guillaume habe ich eine Unterklasse von UIButton als Swift-Datei erstellt. Dann legen Sie meine benutzerdefinierte Klasse im Interface Builder fest:

Interface Builder.

Und hier die Swift-Datei:

import UIKit

class TRAspectButton : UIButton {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.imageView?.contentMode = .ScaleAspectFit
    }
}

-1

Ich hatte das gleiche Problem, aber ich konnte es nicht zum Laufen bringen (vielleicht ist es ein Fehler mit dem SDK).

Als Problemumgehung platzierte ich schließlich ein UIImageViewhinter meinem Button und stellte die gewünschten Optionen ein. Dann platzierte ich einfach ein Leerzeichen UIButtondarüber.


7
Gibt es hier ein Echo? ;-)
Dan Ray
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.