Oto ogólne rozwiązanie pozwalające na umieszczanie obrazu pośrodku tekstu bez używania magicznych liczb. Zwróć uwagę, że poniższy kod jest nieaktualny i prawdopodobnie powinieneś użyć jednej ze zaktualizowanych wersji poniżej :
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
Poniższa wersja zawiera zmiany obsługujące iOS 7+ , które zostały zalecane w komentarzach poniżej. Sam nie testowałem tego kodu, więc nie jestem pewien, jak dobrze działa i czy zepsułby się, gdyby był używany w poprzednich wersjach iOS.
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);
Wersja Swift 5.0
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = imageView?.image?.size,
let text = titleLabel?.text,
let font = titleLabel?.font
else { return }
titleEdgeInsets = UIEdgeInsets(
top: 0.0,
left: -imageSize.width,
bottom: -(imageSize.height + spacing),
right: 0.0
)
let titleSize = text.size(withAttributes: [.font: font])
imageEdgeInsets = UIEdgeInsets(
top: -(titleSize.height + spacing),
left: 0.0,
bottom: 0.0, right: -titleSize.width
)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
contentEdgeInsets = UIEdgeInsets(
top: edgeOffset,
left: 0.0,
bottom: edgeOffset,
right: 0.0
)
}
}
button.currentTitle
a niebutton.titleLabel.text
zwłaszcza, jeśli tekst przycisku kiedykolwiek się zmieni.currentTitle
jest wypełniany od razu,titleLabel.text
ale jego zmiana może być powolna, co może prowadzić do nieprawidłowego wyrównania wstawek.Znalazłem jak.
Najpierw skonfiguruj tekst
titleLabel
(ze względu na style, tj. Pogrubienie, kursywa itp.). Następnie użyjsetTitleEdgeInsets
biorąc pod uwagę szerokość obrazu:Następnie użyj
setTitleEdgeInsets
biorąc pod uwagę szerokość granic tekstu:Teraz obraz i tekst zostaną wyśrodkowane (w tym przykładzie obraz pojawi się nad tekstem).
Twoje zdrowie.
źródło
Możesz to zrobić za pomocą tego rozszerzenia Swift, które zostało częściowo oparte na odpowiedzi Jesse Crossena:
Definiuje funkcję,
centerLabelVerticallyWithPadding
która odpowiednio ustawia wstawki tytułu i obrazu.Ustawia również contentEdgeInsets, co moim zdaniem jest konieczne, aby zapewnić, że
intrinsicContentSize
nadal działa poprawnie, co wymagałoby użycia automatycznego układu.Uważam, że wszystkie rozwiązania podklasy UIButton są technicznie nieuzasadnione, ponieważ nie powinno się tworzyć podklasy kontrolek UIKit. To znaczy teoretycznie mogą się zepsuć w przyszłych wydaniach.
źródło
Edycja: zaktualizowano dla Swift 3
Jeśli szukasz szybkiego rozwiązania odpowiedzi Jesse Crossena, możesz dodać to do podklasy UIButton:
źródło
Jest tutaj kilka świetnych przykładów, ale nie mogłem tego uruchomić we wszystkich przypadkach, gdy mam do czynienia z wieloma wierszami tekstu (zawijanie tekstu). Aby w końcu zadziałało, połączyłem kilka technik:
Użyłem powyższego przykładu Jesse Crossena. Jednak naprawiłem problem z wysokością tekstu i dodałem możliwość określenia poziomego marginesu tekstu. Margines jest przydatny, gdy pozwala się na zawijanie tekstu, aby nie uderzał o krawędź przycisku:
Upewnij się, że ustawiłeś etykietę tekstową do zawijania
To zadziała głównie teraz. Jednak miałem kilka przycisków, które nie renderowały poprawnie swojego obrazu. Obraz został przesunięty zbyt daleko w prawo lub w lewo (nie był wyśrodkowany). Więc użyłem techniki zastępowania układu UIButton, aby wymusić wyśrodkowanie imageView.
źródło
Stworzyłem metodę odpowiedzi @ TodCunningham
źródło
Zaktualizowano dla Xcode 11+
Wstawki opisane w mojej oryginalnej odpowiedzi zostały przeniesione do inspektora rozmiaru w nowszych wersjach Xcode. Nie jestem w 100% pewien, kiedy nastąpiła zmiana, ale czytelnicy powinni sprawdzić inspektora rozmiaru, jeśli informacje wstawione nie zostaną znalezione w inspektorze atrybutów. Poniżej znajduje się przykład nowego wstawionego ekranu (znajdującego się u góry inspektora atrybutów rozmiaru od 11.5).
Oryginalna odpowiedź
Nie ma nic złego w innych odpowiedziach, jednak chciałem tylko zauważyć, że to samo zachowanie można osiągnąć wizualnie w Xcode przy użyciu zerowych linii kodu. To rozwiązanie jest przydatne, jeśli nie potrzebujesz obliczonej wartości lub budujesz za pomocą storyboardu / xib (w przeciwnym razie mają zastosowanie inne rozwiązania).
Uwaga - rozumiem, że pytanie OP wymaga podania kodu. Podaję tylko tę odpowiedź dla kompletności i jako logiczną alternatywę dla tych, którzy używają storyboardów / xibs.
Aby zmodyfikować odstępy w widokach obrazu, tytułu i zawartości przycisku za pomocą wstawek krawędziowych, można zaznaczyć przycisk / element sterujący i otworzyć inspektora atrybutów. Przewiń w dół w kierunku środka inspektora i znajdź sekcję dotyczącą wstawek krawędzi.
Można również uzyskać dostęp i zmodyfikować określone wstawki krawędzi dla widoku tytułu, obrazu lub treści.
źródło
Nie walcz z systemem. Jeśli układy stają się zbyt złożone, aby można było nimi zarządzać za pomocą programu Interface Builder +, być może jakiś prosty kod konfiguracyjny, wykonaj układy ręcznie w prostszy sposób, używając
layoutSubviews
- do tego ! Wszystko inne sprowadzi się do hacków.Utwórz podklasę UIButton i zastąp jej
layoutSubviews
metodę, aby programowo wyrównać tekst i obraz. Lub użyj czegoś takiego jak https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h, aby zaimplementować layoutSubviews za pomocą bloku.źródło
Podklasa UIButton
źródło
Zaktualizowana odpowiedź Jesse Crossena dla Swift 4 :
Użyj w ten sposób:
źródło
Z tym fragmentem kodu otrzymasz coś takiego
źródło
Rozszerzenie UIButton ze składnią Swift 3+ :
Oryginalna odpowiedź: https://stackoverflow.com/a/7199529/3659227
źródło
Tylko niewielka zmiana w odpowiedzi Jessego Crossena, która sprawiła, że działała idealnie:
zamiast:
Użyłem tego:
źródło
Używanie
button.titleLabel.frame.size.width
działa dobrze tylko wtedy, gdy etykieta jest wystarczająco krótka, aby nie została skrócona. Jednak gdy tekst etykiety zostaje obcięty, pozycjonowanie nie działa. Nabierającydziała u mnie nawet wtedy, gdy tekst etykiety jest obcięty.
źródło
Przyjrzałem się istniejącym odpowiedziom, ale odkryłem również, że ustawienie ramki przycisku to ważny pierwszy krok.
Oto funkcja, której używam, która to załatwia:
źródło
Lub możesz po prostu skorzystać z tej kategorii:
źródło
CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Mój przypadek użycia uniemożliwił zarządzanie wstawkami:
Oto, co ostatecznie zrobiłem i jestem z tego całkiem zadowolony:
Utwórz przycisk w serii ujęć z obrazem tła (okrągłe koło z rozmyciem i kolorem).
Zadeklaruj UIImageView w mojej klasie:
Utwórz instancję widoku obrazu na init:
W viewDidLoad dodaj nową warstwę do przycisku naszego widoku obrazu i ustaw wyrównanie tekstu:
W metodzie kliknięcia przycisku dodaj wybrany przeze mnie obraz nakładki do widoku obrazu, dopasuj go do obrazu i wyśrodkuj go w przycisku, ale przesuń go w górę o 15, abym mógł umieścić przesunięcie tekstu poniżej:
Uwaga: funkcja ceilf () jest ważna, aby upewnić się, że znajduje się na granicy pikseli dla jakości obrazu.
źródło
Zakładając, że chcesz, aby zarówno tekst, jak i obraz były wyśrodkowane w poziomie, obraz nad tekstem: Wyśrodkuj tekst z narzędzia do tworzenia interfejsu i dodaj górną wstawkę (robiąc miejsce na obraz). (pozostaw lewą wstawkę na 0). Użyj kreatora interfejsu, aby wybrać obrazek - jego aktualna pozycja zostanie ustawiona z kodu, więc nie martw się, że w IB nie będzie dobrze. W przeciwieństwie do innych odpowiedzi powyżej, to faktycznie działa na wszystkich obecnie obsługiwanych wersjach iOS (5,6 i 7).
W kodzie po prostu odrzuć ImageView przycisku (ustawiając obraz przycisku na null) po przechwyceniu obrazu (spowoduje to również automatyczne wyśrodkowanie tekstu, w razie potrzeby zawijane). Następnie utwórz wystąpienie własnego ImageView z tym samym rozmiarem ramki i obrazem i umieść go pośrodku.
W ten sposób nadal możesz wybrać obraz z konstruktora interfejsu (choć nie zostanie on wyrównany w IB tak jak w symulatorze, ale z drugiej strony inne rozwiązania nie są kompatybilne we wszystkich obsługiwanych wersjach iOS)
źródło
Trudno mi było to zrobić, ponieważ nie mogłem uzyskać rozmiaru obrazu i szerokości tekstu w konstruktorze mojego widoku. Dwie drobne zmiany w odpowiedzi Jessego zadziałały dla mnie:
Zmiana to:
[NSString sizeWithAttributes]
do uzyskania szerokości tekstu;UIImage
zamiastUIImageView
źródło
To działa dobrze w przypadku kilku przycisków, z różną szerokością obrazu i różną długością tytułu:
Podklasa
UIButton
źródło
Działa dobrze dla rozmiaru przycisku 80x80 pikseli.
źródło
Dokonałem pewnych zmian, aby obraz był wyrównany na środku w poziomie:
źródło
czy stosowanie wypustek krawędziowych jest obowiązkowe? Jeśli nie, możesz spróbować ustawić szacunek wobec centralnego poglądu rodzica
źródło
Musisz przesunąć obraz w prawo o szerokość tekstu. Następnie przesuń tekst w lewo o szerokość obrazu.
Następnie wyreguluj górne i dolne wstawki, aby wyregulować oś Y. Prawdopodobnie można to zrobić również programowo, ale powinno być stałe dla rozmiaru obrazu. Podczas gdy wstawki osi X będą musiały się zmieniać w zależności od rozmiaru etykiety tekstowej na każdym przycisku.
źródło
Dodaj ten kod w rozszerzeniu Swift 4.2
źródło
Żeby dorzucić moje 2 centy, to zadziałało dla mnie:
źródło