[ios] UILabel에 윤곽선이있는 텍스트를 표시하려면 어떻게해야합니까?
내가 원하는 것은 흰색 UILabel 텍스트 주위에 1 픽셀의 검은 색 테두리입니다.
나는 아래 코드로 UILabel을 서브 클래 싱하는 데까지 이르렀는데, 접선 적으로 관련된 몇 가지 온라인 예제에서 서투르게 조합했습니다. 그리고 그것은 작동하지만 매우 느립니다 (시뮬레이터 제외) 텍스트를 세로로 중앙에 놓을 수 없었습니다 (그래서 마지막 줄에 y 값을 일시적으로 하드 코딩했습니다). 아아!
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]);
}
나는 이것을하는 더 간단한 방법을 간과하고 있다는 잔소리를 느낀다. 아마도 “drawTextInRect”를 재정의하는 것입니다. 그러나 저는 drawTextInRect를 열심히 쳐다보고 정말 열심히 찌푸리고 있음에도 불구하고 내 의지에 구부러지는 것처럼 보이지 않습니다.
답변
drawTextInRect를 재정 의하여 수행 할 수있었습니다.
- (void)drawTextInRect:(CGRect)rect {
CGSize shadowOffset = self.shadowOffset;
UIColor *textColor = self.textColor;
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, 1);
CGContextSetLineJoin(c, kCGLineJoinRound);
CGContextSetTextDrawingMode(c, kCGTextStroke);
self.textColor = [UIColor whiteColor];
[super drawTextInRect:rect];
CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
self.shadowOffset = shadowOffset;
}
답변
더 간단한 해결책은 다음과 같이 속성 문자열 을 사용하는 것입니다.
스위프트 4 :
let strokeTextAttributes: [NSAttributedStringKey : Any] = [
NSAttributedStringKey.strokeColor : UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -2.0,
]
myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes)
Swift 4.2 :
let strokeTextAttributes: [NSAttributedString.Key : Any] = [
.strokeColor : UIColor.black,
.foregroundColor : UIColor.white,
.strokeWidth : -2.0,
]
myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes)
A의 UITextField
당신은 설정할 수있는 defaultTextAttributes
과를 attributedPlaceholder
잘한다.
참고가 NSStrokeWidthAttributeName
부정적하는 이 경우, 즉, 단지 내부 윤곽 작동합니다.
답변
수락 된 답변과 이에 대한 두 가지 수정 사항 및 Axel Guilmin의 답변을 읽은 후 Swift로 전체 솔루션을 컴파일하기로 결정했습니다.
import UIKit
class UIOutlinedLabel: UILabel {
var outlineWidth: CGFloat = 1
var outlineColor: UIColor = UIColor.whiteColor()
override func drawTextInRect(rect: CGRect) {
let strokeTextAttributes = [
NSStrokeColorAttributeName : outlineColor,
NSStrokeWidthAttributeName : -1 * outlineWidth,
]
self.attributedText = NSAttributedString(string: self.text ?? "", attributes: strokeTextAttributes)
super.drawTextInRect(rect)
}
}
이 사용자 정의 UILabel 클래스를 Interface Builder의 기존 레이블에 추가하고 다음과 같이 사용자 정의 런타임 속성을 추가하여 테두리의 두께와 색상을 변경할 수 있습니다.
결과:
답변
답변의 구현에는 한 가지 문제가 있습니다. 획을 사용하여 텍스트를 그리는 것은 획이없는 텍스트를 그리는 것과 약간 다른 문자 글리프 너비를 가지므로 “중심이없는”결과를 얻을 수 있습니다. 채우기 텍스트 주위에 보이지 않는 선을 추가하여 문제를 해결할 수 있습니다.
바꾸다:
CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
와:
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
self.textColor = textColor;
[[UIColor clearColor] setStroke]; // invisible stroke
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
나는 그것이 진짜 거래인지 100 % 확신하지 못합니다. 왜냐하면 self.textColor = textColor;
과 같은 효과가 있는지는 모르기 때문 [textColor setFill]
입니다.하지만 작동해야합니다.
공개 : 저는 THLabel의 개발자입니다.
얼마 전에 UILabel 하위 클래스를 출시하여 텍스트 및 기타 효과의 개요를 허용합니다. 여기에서 찾을 수 있습니다 : https://github.com/tobihagemann/THLabel
답변
이렇게하면 외곽선이 만들어지지는 않지만 텍스트 주위에 그림자가 생기며 그림자 반경을 충분히 작게 만들면 외곽선과 비슷할 수 있습니다.
label.layer.shadowColor = [[UIColor blackColor] CGColor];
label.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
label.layer.shadowOpacity = 1.0f;
label.layer.shadowRadius = 1.0f;
이전 버전의 iOS와 호환되는지 모르겠습니다 ..
어쨌든 도움이 되었으면합니다 …
답변
kprevas 의 답변을 기반으로 한 Swift 4 클래스 버전
import Foundation
import UIKit
public class OutlinedText: UILabel{
internal var mOutlineColor:UIColor?
internal var mOutlineWidth:CGFloat?
@IBInspectable var outlineColor: UIColor{
get { return mOutlineColor ?? UIColor.clear }
set { mOutlineColor = newValue }
}
@IBInspectable var outlineWidth: CGFloat{
get { return mOutlineWidth ?? 0 }
set { mOutlineWidth = newValue }
}
override public func drawText(in rect: CGRect) {
let shadowOffset = self.shadowOffset
let textColor = self.textColor
let c = UIGraphicsGetCurrentContext()
c?.setLineWidth(outlineWidth)
c?.setLineJoin(.round)
c?.setTextDrawingMode(.stroke)
self.textColor = mOutlineColor;
super.drawText(in:rect)
c?.setTextDrawingMode(.fill)
self.textColor = textColor
self.shadowOffset = CGSize(width: 0, height: 0)
super.drawText(in:rect)
self.shadowOffset = shadowOffset
}
}
UILabel의 사용자 정의 클래스를 OutlinedText로 설정하여 인터페이스 빌더에서 전적으로 구현할 수 있습니다. 그런 다음 속성 창에서 윤곽선의 너비와 색상을 설정할 수 있습니다.
답변
복잡한 애니메이션을 적용하려는 경우 가장 좋은 방법은 대신 애니메이션으로 해당 애니메이션의 스크린 샷을 프로그래밍 방식으로 찍는 것입니다!
뷰의 스크린 샷을 찍으려면 다음과 같은 코드가 필요합니다.
UIGraphicsBeginImageContext(mainContentView.bounds.size);
[mainContentView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
여기서 mainContentView는 스크린 샷을 찍으려는 뷰입니다. UIImageView에 viewImage를 추가하고 애니메이션을 적용합니다.
애니메이션 속도가 빨라지 길 바랍니다 !!
엔