iOS 13의 UISegmentedControl에서 세그먼트 색상을 변경하는 방법은 무엇입니까?


109

A UISegmentedControl는 iOS 13에서 새로운 모습을 보였으며 세그먼트 컨트롤의 색상을 변경하는 기존 코드가 더 이상 작동하지 않습니다.

iOS 13 이전에는 tintColor세그먼트 컨트롤 주변의 테두리, 세그먼트 사이의 선 및 선택한 세그먼트의 배경색에 사용되는 및를 설정할 수있었습니다 . 그런 다음 전경색 속성을 사용하여 각 세그먼트의 제목 색상을 변경할 수 있습니다 titleTextAttributes.

iOS 13 tintColor에서는 아무것도하지 않습니다. 세그먼트 컨트롤의 backgroundColor전체 색상을 변경 하도록 세그먼트 컨트롤을 설정할 수 있습니다 . 그러나 선택한 세그먼트의 배경으로 사용되는 색상을 변경할 방법을 찾을 수 없습니다. 텍스트 속성 설정은 여전히 ​​작동합니다. 제목의 배경색 설정도 시도했지만 선택한 세그먼트의 배경색이 아닌 제목의 배경에만 영향을 미칩니다.

간단히 말해, UISegmentedControliOS 13에서 현재 선택된 세그먼트의 배경색을 어떻게 수정 합니까? private subview 구조를 파헤칠 필요가없는 공용 API를 사용하는 적절한 솔루션이 있습니까?

이 iOS의 13에 새로운 속성없는 UISegmentedControl또는 UIControl과 변화의 아무도는 UIView관련이 없습니다.

답변:


134

아이폰 OS 13b3로, 지금은 거기 selectedSegmentTintColorUISegmentedControl.

세그먼트 컨트롤의 전체 색상을 변경하려면 해당 backgroundColor.

선택한 세그먼트의 색상을 변경하려면을 사용하십시오 selectedSegmentTintColor.

컬러 / 비 선택 세그먼트 타이틀의 폰트 사용을 변경하는 setTitleTextAttributes상태로 .normal/ UIControlStateNormal.

색상 / 선택된 세그먼트 타이틀의 폰트 사용을 변경하는 setTitleTextAttributes상태로 .selected/ UIControlStateSelected.

이미지로 분할 된 컨트롤을 만드는 경우 이미지가 템플릿 이미지로 생성되면 분할 된 컨트롤 tintColor이 이미지의 색상을 지정하는 데 사용됩니다. 그러나 이것은 문제가 있습니다. 를 tintColor동일한 색상으로 설정 selectedSegmentTintColor하면 선택한 세그먼트에 이미지가 표시되지 않습니다. 을와 tintColor같은 색상으로 설정하면 backgroundColor선택되지 않은 세그먼트의 이미지가 표시되지 않습니다. 즉, 이미지가있는 분할 된 컨트롤은 모든 것이 표시 되려면 3 가지 색상을 사용해야합니다. 또는 템플릿이 아닌 이미지를 사용하고 tintColor.

iOS 12 또는 이전 버전에서는 세그먼트 컨트롤을 설정 tintColor하거나 앱의 전체적인 색조 색상에 의존하면됩니다.


테두리없이 세그먼트 컨트롤러를 어떻게 설정합니까? iOS 13에서는 이에 대한 설정이 없습니다. 이전에는 경계선없는 세그먼트 제어를 얻기 위해 색조 설정만으로 충분했습니다.
Deepak Sharma

모든 세그먼트 색상 관련 문제가 여기에서 해결 될 수 있도록 테두리 색상 등을 추가하세요. 뭐라고? :)
Yogesh Patel

1
@YogeshPatel 테두리 색상은 어떻습니까? iOS 13에는 테두리 색상이 없으며 iOS 12에서는 tintColor이미 답변에 포함 된 설정입니다 .
rmaddy

@rmaddy 나는 이것을 설정했다 [segmentedControl.layer setBorderColor : [[UIColor whiteColor] CGColor]]; [segmentedControl.layer setBorderWidth : 0.5]; 그것은 아이폰 OS (13) 나에게 테두리와 테두리 색상을 제공합니다
인 Yogesh 파텔에게

1
아, 그 경계. 이는 세그먼트 화 된 컨트롤뿐만 아니라 모든보기에 적용됩니다. 그것은 원래 질문과이 답변의 범위를 벗어납니다. 귀하의 의견으로 충분합니다.
rmaddy

47

Xcode 11 베타 3 기준

이제에 selectedSegmentTintColor속성이 있습니다 UISegmentedControl.

참조 rmaddy의 답변을


iOS 12 모양을 되돌리려면

선택한 세그먼트의 색상을 칠할 수 없었습니다. 다가오는 베타에서 수정되기를 바랍니다.

선택한 상태의 배경 이미지 설정은 정상 상태의 배경 이미지를 설정하지 않으면 작동하지 않습니다 (모든 iOS 13 스타일링 제거).

하지만 iOS 12 모양으로 되돌릴 수있었습니다 (또는 거의 모서리 반경을 더 작은 크기로 되돌릴 수 없었습니다).

이상적이지는 않지만 밝은 흰색 세그먼트 컨트롤이 앱에서 약간 어색해 보입니다.

( UIImage(color:)우리 코드베이스의 확장 메서드 라는 것을 몰랐습니다 . 그러나이를 구현하는 코드는 웹에 있습니다.)

extension UISegmentedControl {
    /// Tint color doesn't have any effect on iOS 13.
    func ensureiOS12Style() {
        if #available(iOS 13, *) {
            let tintColorImage = UIImage(color: tintColor)
            // Must set the background image for normal to something (even clear) else the rest won't work
            setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
            setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
            setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
            setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
            layer.borderWidth = 1
            layer.borderColor = tintColor.cgColor
        }
    }
}

위 코드의 효과를 보여주는 이미지


이것은 좋은 해결 방법이 될 수 있습니다. 아직 시도해 볼 기회가 없었지만 setTitleTextAttributes선택한 세그먼트의 제목을 흰색으로 만들기 위해 호출해야 합니까?
rmaddy

흠, 그래야 할 것 같지만 그렇지 않은 것 같습니다. 해당 코드 사용 atm에 대한 액세스 권한이 없지만 왼쪽의 이미지는 해당 코드로 생성됩니다.
조나단.

8
UIImage (color :) 확장의 경우 stackoverflow.com/a/33675160/5790492 .
Nik Kov

1
당신이있는 UIImage 확장,이 방법을 추가 할 경우, 당신의 대답이 완료 IHO없는 좋은 일 것입니다
FredFlinstone

1
@VityaShurapov는 강조 표시 되고 선택 될 때 설정하는 것으로 , 전달 된 상태 배열이 아니라 옵션 집합으로, 값이 결합되어 새 상태를 만듭니다.
조나단.

36

IOS 13 및 Swift 5.0 (Xcode 11.0) 세그먼트 제어 100 % 작동

여기에 이미지 설명 입력

여기에 이미지 설명 입력

 if #available(iOS 13.0, *) {
      yoursegmentedControl.backgroundColor = UIColor.black
      yoursegmentedControl.layer.borderColor = UIColor.white.cgColor
      yoursegmentedControl.selectedSegmentTintColor = UIColor.white
      yoursegmentedControl.layer.borderWidth = 1

      let titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]    
      yoursegmentedControl.setTitleTextAttributes(titleTextAttributes, for:.normal)

      let titleTextAttributes1 = [NSAttributedString.Key.foregroundColor: UIColor.black]
      yoursegmentedControl.setTitleTextAttributes(titleTextAttributes1, for:.selected)
  } else {
              // Fallback on earlier versions
}

7
배경을 흰색으로 설정해 보셨습니까? 나를 위해 그것은 s greyish
Ronit

@ItanHant 어떤 xcode와 신속한 언어를 사용하고 있습니까?
Maulik Patel

@Ronit ofcourse !! 나는 시도 할 것이지만 plz는 지금 어떤 유형의 출력 디스플레이를 말해줘
Maulik Patel

신속한 5, xcode 11.3! 그것은 그것이 원하는 것을 보여줍니다! 내가 원하는 것이 아닙니다 :)
Itan Hant

15

나는 해결 방법을 시도했고 그것은 나를 위해 잘 작동합니다. Objective-C 버전은 다음과 같습니다.

@interface UISegmentedControl (Common)
- (void)ensureiOS12Style;
@end
@implementation UISegmentedControl (Common)
- (void)ensureiOS12Style {
    // UISegmentedControl has changed in iOS 13 and setting the tint
    // color now has no effect.
    if (@available(iOS 13, *)) {
        UIColor *tintColor = [self tintColor];
        UIImage *tintColorImage = [self imageWithColor:tintColor];
        // Must set the background image for normal to something (even clear) else the rest won't work
        [self setBackgroundImage:[self imageWithColor:self.backgroundColor ? self.backgroundColor : [UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:tintColorImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:[self imageWithColor:[tintColor colorWithAlphaComponent:0.2]] forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:tintColorImage forState:UIControlStateSelected|UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self setTitleTextAttributes:@{NSForegroundColorAttributeName: tintColor, NSFontAttributeName: [UIFont systemFontOfSize:13]} forState:UIControlStateNormal];
        [self setDividerImage:tintColorImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        self.layer.borderWidth = 1;
        self.layer.borderColor = [tintColor CGColor];
    }
}

- (UIImage *)imageWithColor: (UIColor *)color {
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return theImage;
}
@end

2
나는 그것이 맞는지 확실하지 않다 CGRectMake(0.0f, 0.0f, 1.0f, 1.0f): 엑스 코드 (11) 베타 내 시험에서, rect세그먼트 컨트롤의 범위와 같은 크기로했다.
Cœur

2
iOS13 베타 6부터 색조 색상이 선택한 버튼에 표시되지 않았으므로 다음 줄을 추가해야했습니다. [self setTitleTextAttributes : @ {NSForegroundColorAttributeName : UIColor.blackColor, NSFontAttributeName : [UIFont systemFontOfSize : 13]} forState : UIControlStateSelected];
Peter Johnson

이것을 사용하려고 [[UISegmentedControl appearance] ensureiOS12Style]하면 예외가 발생합니다. 무슨 일이 일어나고 있는지 아십니까? Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSMethodSignature getArgumentTypeAtIndex:]: index (2) out of bounds [0, 1]'
Jeremy Hicks

13

Xcode 11 베타 3 기준

이제에 selectedSegmentTintColor속성이 있습니다 UISegmentedControl.

@rmaddy 감사합니다!


Xcode 11 베타 및 베타 2의 원래 답변

private subview 구조를 파헤칠 필요가없는 공용 API를 사용하는 적절한 솔루션이 있습니까?

Xcode 11.0 베타에서는 기본적으로 모든 상태의 모든 배경 이미지를 둥근 모서리, 투명도 및 resizableImage(withCapInsets:). 예를 들어 다음과 유사한 컬러 이미지를 생성해야합니다.
여기에 이미지 설명 입력

따라서 지금은 하위 뷰를 파헤치는 방법이 훨씬 쉬워 보입니다.

class TintedSegmentedControl: UISegmentedControl {

    override func layoutSubviews() {
        super.layoutSubviews()

        if #available(iOS 13.0, *) {
            for subview in subviews {
                if let selectedImageView = subview.subviews.last(where: { $0 is UIImageView }) as? UIImageView,
                    let image = selectedImageView.image {
                    selectedImageView.image = image.withRenderingMode(.alwaysTemplate)
                    break
                }
            }
        }
    }
}

이 솔루션은 다음과 같이 색조 색상을 선택 항목에 올바르게 적용합니다. 여기에 이미지 설명 입력


1
시간이 부족하기 때문에 수여되지만 개인 계층 구조를 파헤치는 것과 관련이없는 솔루션을 찾는 것이 바람직합니다
.

@홍옥. 감사합니다. 일단 당신 때문에 : 당신은 이미 가장 가까운 솔루션은 계층 구조에서 찾고 관련되지 얻었다 setBackgroundImage을위한 .normal, 당신이 (다른 국가를 포함한 모든 다른 이미지를 설정해야합니다 setDividerImage) 아마 일부, UIBezierPath그리고 resizableImage(withCapInsets:)우리는 아이폰 OS (13) 디자인을 원하는 경우가 지나치게 복잡하게하는, 이 방법.
Cœur 19

그래, 이상적으로 그것은 베타에서 해결 될 것입니다
조나단.

3
iOS 13b3부터는 더 이상 필요하지 않습니다. 이제에 selectedSegmentTintColor속성이 있습니다 UISegmentedControl.
rmaddy

11

@Ilahi Charfeddine 답변의 스위프트 버전 :

if #available(iOS 13.0, *) {
   segmentedControl.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
   segmentedControl.selectedSegmentTintColor = UIColor.blue
} else {
   segmentedControl.tintColor = UIColor.blue
}

10
if (@available(iOS 13.0, *)) {

    [self.segmentedControl setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName: [UIFont systemFontOfSize:13]} forState:UIControlStateSelected];
    [self.segmentedControl setSelectedSegmentTintColor:[UIColor blueColor]];

} else {

[self.segmentedControl setTintColor:[UIColor blueColor]];}

7

iOS13 UISegmentController

사용하는 방법:

segment.setOldLayout(tintColor: .green)

extension UISegmentedControl
{
    func setOldLayout(tintColor: UIColor)
    {
        if #available(iOS 13, *)
        {
            let bg = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
             let devider = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))

             //set background images
             self.setBackgroundImage(bg, for: .normal, barMetrics: .default)
             self.setBackgroundImage(devider, for: .selected, barMetrics: .default)

             //set divider color
             self.setDividerImage(devider, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

             //set border
             self.layer.borderWidth = 1
             self.layer.borderColor = tintColor.cgColor

             //set label color
             self.setTitleTextAttributes([.foregroundColor: tintColor], for: .normal)
             self.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
        }
        else
        {
            self.tintColor = tintColor
        }
    }
}
extension UIImage {
    convenience init(color: UIColor, size: CGSize) {
        UIGraphicsBeginImageContextWithOptions(size, false, 1)
        color.set()
        let ctx = UIGraphicsGetCurrentContext()!
        ctx.fill(CGRect(origin: .zero, size: size))
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        self.init(data: image.pngData()!)!
    }
}

1
이것이 저에게 효과가 있었던 유일한 방법 인 배경 이미지입니다. selectedSegmentTintColor가 어떤 이유로 작동하지 않았습니다.
DenNukem

7

XCODE 11.1 및 iOS 13

@Jigar Darji의 답변을 기반으로하지만 더 안전한 구현입니다.

먼저 실패 할 수있는 편의 이니셜 라이저를 만듭니다.

extension UIImage {

convenience init?(color: UIColor, size: CGSize) {
    UIGraphicsBeginImageContextWithOptions(size, false, 1)
    color.set()
    guard let ctx = UIGraphicsGetCurrentContext() else { return nil }
    ctx.fill(CGRect(origin: .zero, size: size))
    guard
        let image = UIGraphicsGetImageFromCurrentImageContext(),
        let imagePNGData = image.pngData()
        else { return nil }
    UIGraphicsEndImageContext()

    self.init(data: imagePNGData)
   }
}

그런 다음 UISegmentedControl을 확장합니다.

extension UISegmentedControl {

func fallBackToPreIOS13Layout(using tintColor: UIColor) {
    if #available(iOS 13, *) {
        let backGroundImage = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
        let dividerImage = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))

        setBackgroundImage(backGroundImage, for: .normal, barMetrics: .default)
        setBackgroundImage(dividerImage, for: .selected, barMetrics: .default)

        setDividerImage(dividerImage,
                        forLeftSegmentState: .normal,
                        rightSegmentState: .normal, barMetrics: .default)

        layer.borderWidth = 1
        layer.borderColor = tintColor.cgColor

        setTitleTextAttributes([.foregroundColor: tintColor], for: .normal)
        setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
    } else {
        self.tintColor = tintColor
    }
  }
}

완전한! 감사합니다!
Senocico Stelian

5

다음은 Xamarin.iOS (C #)에 대한 Jonathan.의 답변이지만 이미지 크기 조정에 대한 수정 사항입니다. Colin Blake의 답변에 대한 Cœur의 의견과 마찬가지로, 분할기를 제외한 모든 이미지를 분할 된 컨트롤의 크기로 만들었습니다. 구분선은 세그먼트 높이의 1 배입니다.

public static UIImage ImageWithColor(UIColor color, CGSize size)
{
    var rect = new CGRect(0, 0, size.Width, size.Height);
    UIGraphics.BeginImageContext(rect.Size);
    var context = UIGraphics.GetCurrentContext();
    context.SetFillColor(color.CGColor);
    context.FillRect(rect);
    var image = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return image;
}

// https://stackoverflow.com/a/56465501/420175
public static void ColorSegmentiOS13(UISegmentedControl uis, UIColor tintColor, UIColor textSelectedColor, UIColor textDeselectedColor)
{
    if (!UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    {
        return;
    }

    UIImage image(UIColor color)
    {
        return ImageWithColor(color, uis.Frame.Size);
    }

    UIImage imageDivider(UIColor color)
    {
        return ImageWithColor(color, 1, uis.Frame.Height);
    }

    // Must set the background image for normal to something (even clear) else the rest won't work
    //setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
    uis.SetBackgroundImage(image(UIColor.Clear), UIControlState.Normal, UIBarMetrics.Default);

    // setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor), UIControlState.Selected, UIBarMetrics.Default);

    // setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor.ColorWithAlpha(0.2f)), UIControlState.Highlighted, UIBarMetrics.Default);

    // setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor), UIControlState.Highlighted | UIControlState.Selected, UIBarMetrics.Default);

    // setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
    // Change: support distinct color for selected/de-selected; keep original font
    uis.SetTitleTextAttributes(new UITextAttributes() { TextColor = textDeselectedColor }, UIControlState.Normal); //Font = UIFont.SystemFontOfSize(13, UIFontWeight.Regular)
    uis.SetTitleTextAttributes(new UITextAttributes() { TextColor = textSelectedColor, }, UIControlState.Selected); //Font = UIFont.SystemFontOfSize(13, UIFontWeight.Regular)

    // setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    uis.SetDividerImage(imageDivider(tintColor), UIControlState.Normal, UIControlState.Normal, UIBarMetrics.Default);

    //layer.borderWidth = 1
    uis.Layer.BorderWidth = 1;

    //layer.borderColor = tintColor.cgColor
    uis.Layer.BorderColor = tintColor.CGColor;
}

3

다음 방법을 구현할 수 있습니다.

extension UISegmentedControl{
    func selectedSegmentTintColor(_ color: UIColor) {
        self.setTitleTextAttributes([.foregroundColor: color], for: .selected)
    }
    func unselectedSegmentTintColor(_ color: UIColor) {
        self.setTitleTextAttributes([.foregroundColor: color], for: .normal)
    }
}

사용 코드

segmentControl.unselectedSegmentTintColor(.white)
segmentControl.selectedSegmentTintColor(.black)

0

위의 답변은 훌륭하지만 대부분은 선택한 세그먼트 내의 텍스트 색상이 잘못되었습니다. UISegmentedControliOS 13 및 iOS 13 이전 기기에서 사용할 수 있고 iOS 13 이전 기기에서와 마찬가지로 tintColor 속성을 사용할 수있는 하위 클래스를 만들었습니다 .

    class LegacySegmentedControl: UISegmentedControl {
        private func stylize() {
            if #available(iOS 13.0, *) {
                selectedSegmentTintColor = tintColor
                let tintColorImage = UIImage(color: tintColor)
                setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
                setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
                setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
                setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
                setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)

                setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
                layer.borderWidth = 1
                layer.borderColor = tintColor.cgColor

// Detect underlying backgroundColor so the text color will be properly matched

                if let background = backgroundColor {
                    self.setTitleTextAttributes([.foregroundColor: background, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
                } else {
                    func detectBackgroundColor(of view: UIView?) -> UIColor? {
                        guard let view = view else {
                            return nil
                        }
                        if let color = view.backgroundColor, color != .clear {
                            return color
                        }
                        return detectBackgroundColor(of: view.superview)
                    }
                    let textColor = detectBackgroundColor(of: self) ?? .black

                    self.setTitleTextAttributes([.foregroundColor: textColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
                }
            }
        }

        override func tintColorDidChange() {
            super.tintColorDidChange()
            stylize()
        }
    }

    fileprivate extension UIImage {
        public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
          let rect = CGRect(origin: .zero, size: size)
          UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
          color.setFill()
          UIRectFill(rect)
          let image = UIGraphicsGetImageFromCurrentImageContext()
          UIGraphicsEndImageContext()

          guard let cgImage = image?.cgImage else { return nil }
          self.init(cgImage: cgImage)
        }
    }

tintColorDidChange메서드를 사용 하여 세그먼트 뷰 또는 기본 뷰 stylize에서 tintColor속성이 변경 될 때마다 메서드가 호출 되는지 확인합니다. 이는 iOS에서 선호되는 동작입니다.

결과: 여기에 이미지 설명 입력


-2

둥근 모서리를 원하지 않는 경우 Jonathan 대답에서 약간 확장

extension UISegmentedControl {
    /// Tint color doesn't have any effect on iOS 13.
    func ensureiOS12Style(roundCorner: Bool = true) {
        if #available(iOS 13, *) {
            let tintColorImage = UIImage(color: tintColor)
            // Must set the background image for normal to something (even clear) else the rest won't work
            setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
            setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
            setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
            setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

            if !roundCorner {
                layer.masksToBounds = false

                let borderView = UIView()
                borderView.layer.borderWidth = 1
                borderView.layer.borderColor = UIColor.black.cgColor
                borderView.isUserInteractionEnabled = false
                borderView.translatesAutoresizingMaskIntoConstraints = false

                addSubview(borderView)

                NSLayoutConstraint(item: borderView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1, constant: 0).isActive = true
            }
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.