Mam kilka przycisków UIB, aw IB są ustawione na Aspect Fit, ale z jakiegoś powodu zawsze się rozciągają. Czy jest coś jeszcze, co musisz ustawić? Wypróbowałem wszystkie różne tryby widoku i żaden z nich nie działa, wszystkie są rozciągane.
Mam kilka przycisków UIB, aw IB są ustawione na Aspect Fit, ale z jakiegoś powodu zawsze się rozciągają. Czy jest coś jeszcze, co musisz ustawić? Wypróbowałem wszystkie różne tryby widoku i żaden z nich nie działa, wszystkie są rozciągane.
Odpowiedzi:
Miałem ten problem wcześniej. Rozwiązałem to, umieszczając mój obraz w miejscu UIImageView
, w którym contentMode
ustawienia faktycznie działają, i dodając do tego przezroczysty niestandardowy element UIButton
.
EDYCJA: Ta odpowiedź jest przestarzała. Zobacz odpowiedź @Werner Altewischer, aby uzyskać poprawną odpowiedź w nowoczesnych wersjach iOS.
Rozwiązaniem jest ustawienie contentMode
we imageView
właściwości UIButton
. Aby UIButton
to działało, należy utworzyć z typem niestandardowym (w przeciwnym razie nil
jest zwracany dla tej właściwości).
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
button.imageView!.contentMode = UIViewContentMode.scaleAspectFit
Ta metoda zadziałała dla mnie bardzo dobrze .:
W Xib wybierz przycisk i ustaw user defined runtime attributes
:
self.imageView.contentMode
Number
1
Używamy liczby, ponieważ nie możesz tam użyć enum. Ale UIViewContentModeScaleAspectFit jest równa 1.
extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } }
imageView.contentMode
działało na mnie!
Użyj imageView przycisku dla contentMode. Nie bezpośrednio na samym przycisku.
homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];
Jeśli umieścisz obraz w miejscu UIImageView
za przyciskiem, stracisz wbudowaną funkcjonalność UIButton
klasy, taką jak adjustsImageWhenHighlighted
i adjustsImageWhenDisabled
, oraz oczywiście możliwość ustawiania różnych obrazów dla różnych stanów (bez mglistego robienia tego samodzielnie).
Jeśli chcemy, aby obraz był nierozciągnięty dla wszystkich stanów kontrolnych , jednym zatwierdzeniem jest pobranie obrazu za pomocą imageWithCGImage:scale:orientation
, jak w poniższej metodzie:
- (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;
}
Aby to zrealizować, napisalibyśmy:
UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];
Powinno to zapobiec rozciągnięciu obrazu we wszystkich stanach kontrolnych. U mnie zadziałało, ale daj mi znać, jeśli nie!
UWAGA: tutaj zajmujemy się problemem związanym z UIButton
, ale insideButton:
równie dobrze może być insideView:
lub cokolwiek chciałoby się dopasować do obrazu.
Miałem ten problem jakiś czas temu. Problem polegał na tym, że próbowałem zastosować ten efekt do przycisku UIButton w tle, który jest ograniczony i dlatego nie można go tak łatwo dostosować.
Sztuczka polega na tym, aby ustawić go jako zwykły obraz, a następnie zastosować technikę @ ayreguitar i to powinno to naprawić!
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];
To zadziałało dla mnie
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
Dziękuję @ayreguitar za komentarz
Oto szybka alternatywna odpowiedź:
myButton.imageView?.contentMode = .ScaleAspectFit
Łącząc razem kilka różnych odpowiedzi w jedno rozwiązanie - utwórz przycisk o niestandardowym typie, ustaw właściwość imageView contentMode przycisku i ustaw obraz dla przycisku (nie obraz tła, który nadal będzie skalowany do wypełnienia).
//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)
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
Ta odpowiedź jest oparta na odpowiedzi @ WernerAltewischer .
Aby uniknąć podłączenia mojego przycisku do IBOutlet w celu wykonania na nim kodu, podklasowałem klasę UIButton:
// .h
@interface UIButtonWithImageAspectFit : UIButton
@end
// .m
@implementation UIButtonWithImageAspectFit
- (void) awakeFromNib {
[self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}
@end
Teraz utwórz niestandardowy przycisk w swoim xib i ustaw jego obraz (nie obraz tła):
Następnie ustaw jego klasę:
Jesteś skończony!
Zamiast tego
, dopasowanie obrazu przycisku jest teraz zgodne z oczekiwaniami:
ios 12. Musisz także dodać wyrównanie zawartości
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()
}
}
Tryby zawartości UIView mają zastosowanie do odpowiedniej „zawartości” CALayera. Działa to w przypadku UIImageView
s, ponieważ ustawiają CALayer
treść na odpowiednie CGImage
.
drawRect:
ostatecznie renderuje do zawartości warstwy.
Niestandardowy UIButton
(o ile wiem) nie ma zawartości (przyciski w stylu zaokrąglonego prostokąta mogą być renderowane przy użyciu zawartości). Przycisk ma podglądy: tło UIImageView
, obraz UIImageView
i tytuł UILabel
. UstawianiecontentMode
podrzędnego może zrobić, co chcesz, ale majstrowanie przy UIButton
hierarchii widoków jest trochę niemożliwe.
Zmiana UIButton.imageView.contentMode
nie działa na mnie.
Rozwiązałem problem, ustawiając obraz na właściwość „Tło”.
W razie potrzeby możesz dodać ograniczenie współczynnika
To pokrywa się z wieloma innymi odpowiedziami, ale rozwiązaniem dla mnie było
contentMode
z UIImageView
na przycisku do .ScaleAspectFit
- który może być sporządzona w „Użytkownika Runtime Atrybuty” w konstruktorze Interface (tj. self.imageView.contentMode
, liczba, 1) lub w UIButton
podklasie;Podobnie jak @Guillaume, utworzyłem podklasę UIButton jako plik Swift. Następnie ustaw moją klasę niestandardową w Interface Builder:
A tutaj plik Swift:
import UIKit
class TRAspectButton : UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .ScaleAspectFit
}
}
Miałem ten sam problem, ale nie mogłem go uruchomić (być może jest to błąd w SDK).
Ostatecznie, jako obejście, umieściłem UIImageView
za moim przyciskiem i ustawiłem opcje, które chciałem, a następnie po prostu umieściłem na nim puste UIButton
miejsce.