Wszystko, czego chcę, to czarne obramowanie jednego piksela wokół mojego białego tekstu UILabel.
Dotarłem do podklasy UILabel za pomocą poniższego kodu, który niezdarnie zebrałem razem z kilku stycznie powiązanych przykładów online. I działa, ale jest bardzo, bardzo powolny (z wyjątkiem symulatora) i nie mogłem go również wyśrodkować tekstu w pionie (więc tymczasowo zakodowałem na stałe wartość y w ostatnim wierszu). Ahhhh!
void ShowStringCentered(CGContextRef gc, float x, float y, const char *str) {
CGContextSetTextDrawingMode(gc, kCGTextInvisible);
CGContextShowTextAtPoint(gc, 0, 0, str, strlen(str));
CGPoint pt = CGContextGetTextPosition(gc);
CGContextSetTextDrawingMode(gc, kCGTextFillStroke);
CGContextShowTextAtPoint(gc, x - pt.x / 2, y, str, strlen(str));
}
- (void)drawRect:(CGRect)rect{
CGContextRef theContext = UIGraphicsGetCurrentContext();
CGRect viewBounds = self.bounds;
CGContextTranslateCTM(theContext, 0, viewBounds.size.height);
CGContextScaleCTM(theContext, 1, -1);
CGContextSelectFont (theContext, "Helvetica", viewBounds.size.height, kCGEncodingMacRoman);
CGContextSetRGBFillColor (theContext, 1, 1, 1, 1);
CGContextSetRGBStrokeColor (theContext, 0, 0, 0, 1);
CGContextSetLineWidth(theContext, 1.0);
ShowStringCentered(theContext, rect.size.width / 2.0, 12, [[self text] cStringUsingEncoding:NSASCIIStringEncoding]);
}
Mam tylko dokuczliwe uczucie, że pomijam prostszy sposób, aby to zrobić. Być może przez nadpisanie „drawTextInRect”, ale wydaje mi się, że drawTextInRect w ogóle nie nagina się do mojej woli, mimo że wpatruję się w to uważnie i marszczy brwi.
ios
objective-c
iphone
cocoa-touch
core-graphics
Monte Hurd
źródło
źródło
Odpowiedzi:
Udało mi się to zrobić, zastępując drawTextInRect:
źródło
UILabel
i umieścić-drawTextInRect:
tam implementację.Prostszym rozwiązaniem jest użycie przypisanego ciągu w następujący sposób:
Swift 4:
Swift 4.2:
Na a
UITextField
możesz również ustawićdefaultTextAttributes
iattributedPlaceholder
.Zauważ, że w tym przypadku wartość
NSStrokeWidthAttributeName
musi być ujemna , tzn. Działają tylko wewnętrzne kontury.źródło
Po przeczytaniu zaakceptowanej odpowiedzi i dwóch poprawkach do niej oraz odpowiedzi od Axela Guilmina, zdecydowałem się skompilować w Swift całościowe rozwiązanie, które mi odpowiada:
Możesz dodać tę niestandardową klasę UILabel do istniejącej etykiety w Interface Builder i zmienić grubość obramowania i jej kolor, dodając zdefiniowane przez użytkownika atrybuty środowiska wykonawczego w następujący sposób:
Wynik:
źródło
Jest jeden problem z implementacją odpowiedzi. Rysowanie tekstu z obrysem ma nieco inną szerokość glifu niż rysowanie tekstu bez obrysu, co może dawać wyniki „bez wyśrodkowania”. Można to naprawić, dodając niewidoczny obrys wokół tekstu wypełnienia.
Zastąpić:
z:
Nie jestem w 100% pewien, czy to prawda, ponieważ nie wiem, czy
self.textColor = textColor;
ma taki sam efekt, jak[textColor setFill]
, ale powinno działać.Ujawnienie: jestem twórcą THLabel.
Niedawno opublikowałem podklasę UILabel, która umożliwia zarys tekstu i inne efekty. Możesz go znaleźć tutaj: https://github.com/tobihagemann/THLabel
źródło
Nie spowoduje to utworzenia konturu jako takiego, ale spowoduje umieszczenie cienia wokół tekstu, a jeśli zmniejszysz promień cienia, może on przypominać kontur.
Nie wiem, czy jest kompatybilny ze starszymi wersjami iOS ..
W każdym razie mam nadzieję, że to pomoże ...
źródło
Wersja klasy Swift 4 oparta na odpowiedzi udzielonej przez kprevas
Można go zaimplementować w całości w Interface Builder, ustawiając niestandardową klasę UILabel na OutlinedText. Będziesz wtedy mieć możliwość ustawienia szerokości i koloru konturu w panelu Właściwości.
źródło
Jeśli chcesz animować coś skomplikowanego, najlepszym sposobem jest programowe zrobienie tego zrzutu ekranu i animacji!
Aby zrobić zrzut ekranu widoku, potrzebujesz trochę takiego kodu:
Gdzie mainContentView to widok, z którego chcesz zrobić zrzut ekranu. Dodaj viewImage do UIImageView i animuj to.
Mam nadzieję, że to przyspieszy twoją animację !!
N
źródło
Jak wspomniał MuscleRumble , granica akceptowanej odpowiedzi jest nieco poza środkiem. Udało mi się to poprawić, ustawiając szerokość obrysu na zero zamiast zmieniać kolor na wyraźny.
czyli wymiana:
z:
Właśnie skomentowałbym jego odpowiedź, ale najwyraźniej nie jestem wystarczająco „renomowany”.
źródło
jeśli WSZYSTKO, czego chcesz, to czarne obramowanie jednego piksela wokół mojego białego tekstu UILabel,
to myślę, że utrudniasz problem, niż jest ... Nie wiem na podstawie pamięci, której funkcji „draw rect / frameRect” powinieneś użyć, ale będzie ci łatwo ją znaleźć. ta metoda po prostu demonstruje strategię (pozwól superklasie wykonać pracę!):
źródło
Znalazłem problem z główną odpowiedzią. Pozycja tekstu niekoniecznie musi być prawidłowo wyśrodkowana względem lokalizacji subpikseli, więc kontur może być niedopasowany dookoła tekstu. Naprawiłem to za pomocą następującego kodu, który używa
CGContextSetShouldSubpixelQuantizeFonts(ctx, false)
:Zakłada się, że zdefiniowałeś
textOutlineColor
itextOutlineWidth
jako właściwości.źródło
Oto kolejna odpowiedź, aby umieścić zarysowany tekst na etykiecie.
ustawić zarysowany tekst po prostu używając metody rozszerzenia.
źródło
możliwe jest również utworzenie podklasy UILabel z następującą logiką:
a jeśli ustawisz tekst w Storyboard, to:
źródło
Jeśli Twoim celem jest coś takiego:
Oto, jak to osiągnąłem: Dodałem nową
label
klasę niestandardową jako Widok podrzędny do mojego obecnego UILabel (zainspirowany tą odpowiedzią ).Po prostu skopiuj i wklej go do swojego projektu i gotowe:
STOSOWANIE:
działa również
UIButton
z wszystkimi jego animacjami:źródło
Dlaczego nie utworzysz obramowania 1px UIView w Photoshopie, a następnie ustawisz UIView z obrazem i nie umieścisz go za UILabel?
Kod:
Zaoszczędzi ci to podklasy obiektu i jest to dość proste.
Nie wspominając o tym, że chcesz tworzyć animacje, jest to wbudowane w klasę UIView.
źródło
Aby umieścić obramowanie z zaokrąglonymi krawędziami wokół UILabel, wykonuję następujące czynności:
(nie zapomnij dołączyć QuartzCore / QuartzCore.h)
źródło