UIButton nie nasłuchuje ustawienia trybu treści?

92

firstButton to UIButton typu Custom. Programowo umieszczam trzy z nich w każdej komórce tabeli, w ten sposób:

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

W innym miejscu mówię mu, aby clipToBounds. To, co otrzymuję, to przycięcie środkowego kwadratu obrazu, a nie jego renderowanie ze skalą proporcji. Próbowałem tego na wiele sposobów, w tym ustawienie właściwości trybu na firstButton.imageView, co również wydaje się nie działać.

Dan Ray
źródło
1
Zobacz rozwiązanie autorstwa Chrisa Noleta poniżej: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt,
Zobacz stackoverflow.com/a/28205566/481207, który pokazuje, że ustawienie zarówno contentVerticalAlignment, jak i contentHorizontalAlignment jest wymagane dla UIViewContentModeScaleAspectFit.
Matt

Odpowiedzi:

187

Miałem ten sam problem. Widzę, że to pytanie jest trochę stare, ale chcę udzielić jasnej i poprawnej odpowiedzi, aby zaoszczędzić innym ludziom (takim jak ja) trochę czasu, gdy pojawi się w ich wynikach wyszukiwania.

Zajęło mi to trochę poszukiwań i eksperymentów, ale znalazłem rozwiązanie. Wystarczy ustawić ContentMode „ukrytego” ImageView, który znajduje się wewnątrz UIButton.

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

Być może do tego nawiązywał Dan Ray w swojej zaakceptowanej odpowiedzi, ale podejrzewam, że nie.

Dave
źródło
1
Nie, nie było. Rozwiązaniem, na które się zdecydowałem, było użycie UIImageView do przechowywania obrazu, a następnie wyraźnego, przezroczystego UIButton typu „custom” na wierzchu.
Dan Ray,
Dave, przynajmniej na iOS 3.2 twoje rozwiązanie wydaje się nie działać dla mnie. Szkoda, ponieważ liczyłem na podświetlenie obrazu po kliknięciu „za darmo”. Upewniłem się nawet, że button.imageView nie jest zerowy, gdy ustawiałem contentMode, i ustawiłem obraz po ustawieniu contentMode, tak jak robisz.
Jacques
2
Dla wyjaśnienia, „nie działa” oznacza, że ​​„obraz jest wyświetlany w pełnej rozdzielczości, a nie pomniejszony, jak się spodziewałem”.
Jacques
Jacques, powyższe działa u mnie w iOS 4.x. Niestety, mogę odtworzyć problem „nie można zmienić rozmiaru” podczas budowania z celem w wersji 3.2. Próbowałem zmienić rozmiar ramki widoku UIButton, ale to też nie pomogło. ugh.
Dave,
4
Zobacz rozwiązanie autorstwa Chrisa Noleta poniżej: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt,
74

Jeśli masz do czynienia z obrazem UIButton (w przeciwieństwie do jego backgroundImage), ustawienie contentMode na samym UIButton lub na jego imageView nie ma wpływu (pomimo tego, co mówią inne odpowiedzi).

Alternatywnie zrób to zamiast tego:

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

Lub odpowiednio dopasuj rozmiar obrazu.

LUB po prostu użyj UIImageView (który odpowiednio szanuje contentMode) z dołączonym do niego UITapGestureRecognizer lub przezroczystym UIButton na wierzchu.

Alfie Hanssen
źródło
4
Działa to w moim przypadku w iOS 7, podczas gdy wszystkie inne tutaj nie.
Bajt
5
Ustawienie contentHorizontalAlignment i contentVerticalAlignment to prawidłowe rozwiązanie. Aby uzyskać wyjaśnienie, zobacz stackoverflow.com/a/28205566/481207 .
Matt
1
To odpowiedź, której szukałem.
ninjaneer
4
Ta odpowiedź jest nieprawidłowa. Państwo nie trzeba ustawić contentModew sprawie imageView, jeśli chcesz zrobić każdy rodzaj wypełnienia kształtu lub dopasowania, jak inne odpowiedzi zostały wyjaśnione. Zobacz: stackoverflow.com/a/7944316/746890 .
Chris Nolet
52

Zamiast ustawiać przycisk contentModena samym przycisku, będziesz chciał ustawić contentHorizontalAlignmenti contentVerticalAlignmentwłaściwości oraz (co najważniejsze) contentModedla przycisku imageViewdla dowolnego rodzaju wypełnienia lub dopasowania. Oto przykład:

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

Oczywiście możesz także wykonać inne czynności, takie jak wyrównanie obrazu przycisku do górnej części przycisku. Jeśli nie potrzebujesz wypełnienia lub dopasowania aspektu, możesz po prostu ustawić wyrównanie samodzielnie:

button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

W Swift będziesz chciał użyć:

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

Działa to dla wszystkich wersji iOS, w tym najnowszych wersji z automatycznym układem (tj. IOS 4 do iOS 11+).

Chris Nolet
źródło
2
Dzięki Chris - to rozwiązało mój problem, a raczej w połączeniu z contentEdgeInsets, aby trochę cofnąć mój obraz od górnej krawędzi.
Rob Reuss,
7

Po kilku godzinach zamieszania, oto jak sprawiłem, że zadziała pod iOS 3.2. Jak wspomniał Dusker, użycie setBackgroundImage zamiast setImage wykonało pracę za mnie.

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
źródło
6

Odpowiedź brzmi: użyj UIImageView ze wszystkimi pięknymi ustawieniami trybu treści, które chcesz, a następnie umieść na nim niestandardowy przycisk. Głupi, że nie możesz tego zrobić za jednym zamachem, ale wydaje się, że nie możesz.

Dan Ray
źródło
4

Znalazłem rozwiązanie tego problemu. Ustaw adjustsImageWhenHighlightedwłaściwość UIButtonto NO.

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

Mam nadzieję że to pomoże. Zapraszam do komentowania poniżej, odpowiem na wszelkie pytania, które masz.

iOSDevSF
źródło
To idealne rozwiązanie.
Gaurav,
Nie działa. Zapobiega to jedynie podświetleniu przycisku.
Matt
4

Moja odpowiedź jest podobna do tej Kuby. Potrzebowałem programowego ustawienia obrazu.

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
źródło
3

Jedyne rozwiązanie, które u mnie zadziałało:

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Tariq
źródło
3

Szybki 3

self.firstButton.imageView?.contentMode = .scaleAspectFill
Vaibhav Saran
źródło
1

Zamiast setImage spróbuj setBackgroundImage

zmierzch
źródło
3
Hmp. A, to głupie, powinno szanować ustawienie CONTENT MODE dla swojej ZAWARTOŚCI, prawda? I B, to NADAL nie wydaje się respektować ustawienia trybu - jest teraz zablokowane na „rozciąganie” (co w tym przypadku bardziej przypomina „squeeze”) i nie skaluje zawartości w odniesieniu do jej aspektu stosunek.
Dan Ray
1

Uważam, że mamy tutaj prosty problem z konstruktorem interfejsu - najwyraźniej IB ignoruje wszelkie zmiany trybu treści PO ustawieniu właściwości obrazu.

rozwiązanie jest tak proste: ustaw tryb treści, usuń wcześniej ustawione nazwy obrazów (upewnij się, że usunąłeś je we wszystkich stanach, domyślnych, podświetlonych itp.), a następnie ponownie wprowadź żądane nazwy obrazów we wszystkich pożądanych stanach - et voilà .

JohnPayne
źródło
1
to samo dotyczy programowego ustawiania trybu treści - nie ustawiaj obrazu PRZED ustawieniem trybu treści
JohnPayne
0

Radzę też przyjrzeć się tej adjustsImageWhenHighlighted UIButtonnieruchomości, aby uniknąć dziwnych deformacji obrazu, gdy przycisk jest wciśnięty.

MonsieurDart
źródło
0

Próbując to rozgryźć, moja metoda stawała się nieco trudniejsza w miarę upływu czasu i zakończyłem podklasę UIButton i nadpisanie setHighlighted:

U mnie działa po prostu obniżyć alfa obrazu do 0,5, ponieważ są na czarnym tle.

Jednak działa to tylko wtedy, gdy skomentuję [super setHighlighted:] (gdzie wygląda na to, że kod jest rozciągliwy na obrazie), co po prostu nie wydaje się być właściwym sposobem rozwiązania tego problemu ... wszystko wydaje się być działa dobrze, chociaż. Zobaczymy, jak to wytrzyma, gdy będę nad nim pracował.

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

//    [super setHighlighted:highlight];
}
jankins
źródło
1
Na wypadek, gdyby ktoś uznał to za istotne, moja powyższa metoda wydawała się działać OK, dopóki nie umieściłem przycisków w UIScrollView, gdzie czasami podświetlenie przycisku „utknęło”, co, jak podejrzewałem, może w końcu się wydarzyć.
jankins
0

Jeśli ktoś szuka odpowiedzi, która działa w iOS 6 i iOS 7 oraz w scenorysie:

Możesz ustawić obraz w swojej serii ujęć:

wprowadź opis obrazu tutaj

I wtedy:

for(UIView* testId in self.subviews) {
    if([testId isKindOfClass:[UIImageView class]])
        [testId setContentMode:UIViewContentModeScaleAspectFill];
}
Kuba
źródło
0

Jeśli wydaje się, że przycisk UIButton nie nasłuchuje ustawień ograniczeń układu, sprawdź, czy obrazy są większe niż rozmiar przycisku. Zawsze używaj obrazów @ 2x i @ 3x dla rozdzielczości siatkówki.

Totoro
źródło
0

Te dwie rzeczy (które na początku są dość trudne do znalezienia) rozciągną twój obraz UIButton, aby dopasować go do rozmiaru przycisku:

wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj

należy zawsze próbować ustawić takie w Storyboard, a nie w kodzie.

delta2flat
źródło