programing

UI 레이블에서 개요 텍스트를 표시하려면 어떻게 해야 합니까?

easyjava 2023. 6. 3. 08:52
반응형

UI 레이블에서 개요 텍스트를 표시하려면 어떻게 해야 합니까?

제가 원하는 것은 흰색 UILabel 텍스트 주위에 1픽셀 검은색 테두리입니다.

저는 아래 코드로 UI 레이블을 하위 분류하는 것까지 얻었는데, 몇 가지 유형적으로 관련된 온라인 예제에서 엉거주춤하게 정리했습니다.작동은 하지만 매우 느리고(시뮬레이터를 제외하고) 텍스트의 중심을 수직으로 잡을 수도 없었습니다(그래서 마지막 줄의 값을 일시적으로 하드 코딩했습니다).아!

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;

}

더 간단한 해결책은 다음과 같은 Attributed String을 사용하는 것입니다.

스위프트 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)

UITextField▁the를 설정할 수.defaultTextAttributes 리고그고.attributedPlaceholder뿐만 아니라.

로 고는 다음과 .NSStrokeWidthAttributeName 경우에는 부정적이어야 합니다. 즉, 내부 개요만 작동합니다.

속성 텍스트를 사용한 개요가 있는 UI 텍스트 필드

승인된 답변과 이에 대한 두 가지 수정 사항 및 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)
    }
}

Runtime 를 다음과 같이 하여 테두리 할 수 .인터페이스 작성기 설정

결과:

윤곽이 있는 큰 빨간색 G

답변의 구현과 관련하여 한 가지 문제가 있습니다.스트로크를 사용하여 텍스트를 그리는 것은 스트로크를 사용하지 않고 텍스트를 그리는 것과 약간 다른 문자 글리프 너비를 가지므로 "중심이 없는" 결과를 생성할 수 있습니다.채우기 텍스트 주위에 보이지 않는 스트로크를 추가하여 수정할 수 있습니다.

대체:

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 에서 확인할 수 있습니다.

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의 사용자 정의 클래스를 OutlookedText로 설정하여 인터페이스 작성기에서 전체적으로 구현할 수 있습니다.그러면 특성 영역에서 윤곽선의 너비와 색상을 설정할 수 있습니다.

여기에 이미지 설명 입력

목표가 다음과 같은 경우:

여기에 이미지 설명 입력

가 그것을과 같습니다: 저는 이를달한다같습다니과음방법은성▁here를 했습니다.label사용자 지정 클래스를 현재 UI 레이블의 Subview로 지정합니다( 답변에서 영감을 얻음).

프로젝트에 복사하여 붙여넣기만 하면 바로 사용할 수 있습니다.

extension UILabel {
    func addTextOutline(usingColor outlineColor: UIColor, outlineWidth: CGFloat) {
        class OutlinedText: UILabel{
            var outlineWidth: CGFloat = 0
            var outlineColor: UIColor = .clear

            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.textAlignment = .center
                self.textColor = outlineColor
                super.drawText(in:rect)

                c?.setTextDrawingMode(.fill)
                self.textColor = textColor
                self.shadowOffset = CGSize(width: 0, height: 0)
                super.drawText(in:rect)

                self.shadowOffset = shadowOffset
            }
        }

        let textOutline = OutlinedText()
        let outlineTag = 9999

        if let prevTextOutline = viewWithTag(outlineTag) {
            prevTextOutline.removeFromSuperview()
        }

        textOutline.outlineColor = outlineColor
        textOutline.outlineWidth = outlineWidth
        textOutline.textColor = textColor
        textOutline.font = font
        textOutline.text = text
        textOutline.tag = outlineTag

        sizeToFit()
        addSubview(textOutline)
        textOutline.frame = CGRect(x: -(outlineWidth / 2), y: -(outlineWidth / 2),
                                   width: bounds.width + outlineWidth,
                                   height: bounds.height + outlineWidth)
    }
}

용도:

yourLabel.addTextOutline(usingColor: .red, outlineWidth: 6)

그것은 또한 효과가 있습니다.UIButton모든 애니메이션과 함께:

yourButton.titleLabel?.addTextOutline(usingColor: .red, outlineWidth: 6)

만약 여러분이 복잡한 것을 애니메이션으로 만들고 싶다면, 가장 좋은 방법은 프로그래밍 방식으로 그것의 스크린샷을 대신 애니메이션으로 찍는 것입니다!

보기의 스크린샷을 만들려면 다음과 같은 코드가 필요합니다.

UIGraphicsBeginImageContext(mainContentView.bounds.size);
[mainContentView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); 

여기서 mainContentView는 스크린샷을 만들려는 보기입니다.UIImageView에 viewImage를 추가하고 애니메이션화합니다.

당신의 애니메이션 속도가 빨라지길 바랍니다!!

N

머슬럼블이 언급했듯이, 받아들여진 답변의 테두리는 중심에서 약간 벗어났습니다.저는 선명한 색상으로 변경하는 대신 스트로크 폭을 0으로 설정하여 수정할 수 있었습니다.

예: 교체:

CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];

포함:

CGContextSetTextDrawingMode(c, kCGTextFillStroke);
self.textColor = textColor;
CGContextSetLineWidth(c, 0); // set stroke width to zero
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];

나는 그의 대답에 대해 그냥 논평했을 것이지만 분명히 나는 충분히 "명망이 있는" 사람이 아닙니다.

이렇게 하면 윤곽선이 개별적으로 생성되지는 않지만 텍스트 주위에 그림자가 드리워지고 그림자 반지름을 충분히 작게 만들면 윤곽선과 유사할 수 있습니다.

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와 호환되는지 모르겠습니다.

어쨌든, 그게 도움이 되길...

당신이 원하는 것이 내 흰색 UILabel 텍스트 주변의 1픽셀 검은색 테두리라면,

그렇다면 당신이 문제를 현재보다 더 어렵게 만들고 있다고 생각합니다.어떤 'drawrect/frameRect' 기능을 사용해야 할지 기억이 안 나지만 쉽게 찾을 수 있을 것입니다.이 방법은 전략을 보여줄 뿐입니다(슈퍼 클래스가 작업을 수행하도록 하십시오!).

- (void)drawRect:(CGRect)rect
{
  [super drawRect:rect];
  [context frameRect:rect]; // research which rect drawing function to use...
}

저는 주요 답변에서 문제점을 발견했습니다.텍스트 위치가 하위 픽셀 위치로 정확하게 중앙에 배치될 필요는 없으므로 텍스트 주위의 윤곽선이 일치하지 않을 수 있습니다.,다고를 사용하는 다음 코드를 사용하여 고쳤습니다.CGContextSetShouldSubpixelQuantizeFonts(ctx, false):

- (void)drawTextInRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    [self.textOutlineColor setStroke];
    [self.textColor setFill];

    CGContextSetShouldSubpixelQuantizeFonts(ctx, false);

    CGContextSetLineWidth(ctx, self.textOutlineWidth);
    CGContextSetLineJoin(ctx, kCGLineJoinRound);

    CGContextSetTextDrawingMode(ctx, kCGTextStroke);
    [self.text drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment];

    CGContextSetTextDrawingMode(ctx, kCGTextFill);
    [self.text drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment];
}

이는 다음과 같이 정의했다고 가정합니다.textOutlineColor그리고.textOutlineWidth재산으로서

다음은 레이블에 요약된 텍스트를 설정하는 또 다른 대답입니다.

extension UILabel {

func setOutLinedText(_ text: String) {
    let attribute : [NSAttributedString.Key : Any] = [
        NSAttributedString.Key.strokeColor : UIColor.black,
        NSAttributedString.Key.foregroundColor : UIColor.white,
        NSAttributedString.Key.strokeWidth : -2.0,
        NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 12)
        ] as [NSAttributedString.Key  : Any]

    let customizedText = NSMutableAttributedString(string: text,
                                                   attributes: attribute)
    attributedText = customizedText
 }

}

확장 방법을 사용하여 개요 텍스트를 설정합니다.

lblTitle.setOutLinedText("Enter your email address or username")

다음 로직을 사용하여 UI 레이블을 하위 분류할 수도 있습니다.

- (void)setText:(NSString *)text {
    [self addOutlineForAttributedText:[[NSAttributedString alloc] initWithString:text]];
}

- (void)setAttributedText:(NSAttributedString *)attributedText {
    [self addOutlineForAttributedText:attributedText];
}

- (void)addOutlineForAttributedText:(NSAttributedString *)attributedText {
    NSDictionary *strokeTextAttributes = @{
                                           NSStrokeColorAttributeName: [UIColor blackColor],
                                           NSStrokeWidthAttributeName : @(-2)
                                           };

    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithAttributedString:attributedText];
    [attrStr addAttributes:strokeTextAttributes range:NSMakeRange(0, attrStr.length)];

    super.attributedText = attrStr;
}

Storyboard에서 텍스트를 설정하는 경우:

- (instancetype)initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    if (self) {
        // to apply border for text from storyboard
        [self addOutlineForAttributedText:[[NSAttributedString alloc] initWithString:self.text]];
    }
    return self;
}

포토샵에서 1px 테두리 UIView를 만든 다음 이미지로 UIView를 설정하고 UILabel 뒤에 배치하는 것은 어떻습니까?

코드:

UIView *myView;
UIImage *imageName = [UIImage imageNamed:@"1pxBorderImage.png"];
UIColor *tempColour = [[UIColor alloc] initWithPatternImage:imageName];
myView.backgroundColor = tempColour;
[tempColour release];

이것은 객체를 하위 분류하는 것을 줄일 수 있고 매우 간단합니다.

애니메이션을 하고 싶다면 말할 것도 없고, 그것은 UIView 클래스에 내장되어 있습니다.

UI 레이블 주위에 둥근 모서리가 있는 테두리를 배치하려면 다음을 수행합니다.

labelName.layer.borderWidth = 1;
labelName.layer.borderColor = [[UIColor grayColor] CGColor];
labelName.layer.cornerRadius = 10;

(QuartzCore/QuartzCore를 포함하는 것을 잊지 마십시오.)

언급URL : https://stackoverflow.com/questions/1103148/how-do-i-make-uilabel-display-outlined-text

반응형