如何在 iOS 13 的 UISegmentedControl 中更改段的颜色?
Posted
技术标签:
【中文标题】如何在 iOS 13 的 UISegmentedControl 中更改段的颜色?【英文标题】:How to change the colors of a segment in a UISegmentedControl in iOS 13? 【发布时间】:2019-10-19 13:14:19 【问题描述】:UISegmentedControl
在 ios 13 中有了新的外观,并且用于更改分段控件颜色的现有代码不再像以前那样工作。
在 iOS 13 之前,您可以设置 tintColor
,它将用于分段控件周围的边框、分段之间的线条以及所选分段的背景颜色。然后,您可以使用 titleTextAttributes
的前景色属性更改每个段的标题颜色。
在 iOS 13 下,tintColor
什么都不做。您可以设置分段控件的backgroundColor
来更改分段控件的整体颜色。但我找不到任何方法来改变用作所选片段背景的颜色。设置文本属性仍然有效。我什至尝试设置标题的背景颜色,但这只会影响标题的背景,而不影响所选片段的其余背景颜色。
简而言之,如何修改iOS 13中UISegmentedControl
当前选中段的背景颜色?是否有适当的解决方案,使用公共 API,不需要深入研究私有子视图结构?
iOS 13 中没有 UISegmentedControl
或 UIControl
的新属性,UIView
中的任何更改都不相关。
【问题讨论】:
【参考方案1】:如果您想将背景设置为清除,您必须这样做:
if #available(iOS 13.0, *)
let image = UIImage()
let size = CGSize(width: 1, height: segmentedControl.intrinsicContentSize.height)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
image.draw(in: CGRect(origin: .zero, size: size))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
segmentedControl.setBackgroundImage(scaledImage, for: .normal, barMetrics: .default)
segmentedControl.setDividerImage(scaledImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
结果如下:
【讨论】:
几乎可以工作,但我在 iOS 14 上,selectedSegmentTintColor
不显示(即选定的段选项是白色而不是我选定的颜色)。【参考方案2】:
在 iOS 13 及更高版本中,当我在viewDidLoad
中访问分段控件的subviews
时,它有1 个UIImageView
。一旦我插入了更多的段,它就会分别增加,所以 3 个段意味着 3 个 UIImageView
作为分段控件的 subviews
。
有趣的是,当它到达viewDidAppear
时,分段控件的subviews
变为3 个UISegment
(每个都包含一个UISegmentLabel
作为其子视图;这是您的文本)和4 个UIImageView
,如下所示:
viewDidLoad
中的 3 个UIImageView
不知何故变成了UISegment
,我们不想触摸它们(但您可以尝试设置它们的图像或isHidden
只是为了看看它如何影响用户界面)。让我们忽略这些私有类。
这 4 个 UIImageView
实际上是 3 个“正常”UIImageView
(连同 1 个 UIImageView
子视图作为垂直分隔符)和 1 个“选定”UIImageView
(即这实际上是您的 selectedSegmentTintColor
图像,注意在上面的截图中,它下面没有子视图)。
就我而言,我需要一个白色背景,所以我必须隐藏灰色背景图像(请参阅:https://medium.com/flawless-app-stories/ios-13-uisegmentedcontrol-3-important-changes-d3a94fdd6763)。我还想删除/隐藏段之间的垂直分隔符。
因此,viewDidAppear
中的简单解决方案,无需设置分隔图像或背景图像(在我的情况下),就是简单地隐藏前 3 个UIImageView
:
// This method might be a bit 'risky' since we are not guaranteed of the internal sequence ordering, but so far it seems ok.
if #available(iOS 13.0, *)
for i in 0...(segmentedControl.numberOfSegments - 1)
segmentedControl.subviews[i].isHidden = true
或
// This does not depend on the ordering sequence like the above, but this is also risky in the sense that if the UISegment becomes UIImageView one day, this will break.
if #available(iOS 13.0, *)
for subview in segmentedControl.subviews
if String(describing: subview).contains("UIImageView"),
subview.subviews.count > 0
subview.isHidden = true
选择你的毒药...
【讨论】:
【参考方案3】:iOS 12+
我为背景颜色做了很多努力。将 .clear 颜色设置为背景色总是添加默认的灰色。这是我修复的方法
self.yourSegmentControl.backgroundColor = .clear //Any Color of your choice
self.yourSegmentControl.setBackgroundImage(UIImage(), for: .normal, barMetrics: .default) //This does the magic
另外用于分隔线颜色
self.yourSegmentControl.setDividerImage(UIImage(), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default) // This will remove the divider image.
【讨论】:
不适合我,整个片段变成白色(在 iOS 14 上测试)。 你设置了什么颜色作为背景色? 如果我没记错的话,我想我使用了白色(或者我根本没有设置它) 尝试将其设置为清除颜色? 是的,这是我尝试的第一件事。白色也适合你吗?【参考方案4】:SwiftUI Picker
缺少一些基本选项。对于尝试在 iOS 13 或 14 的 SwiftUI 中使用 SegmentedPickerStyle() 自定义 Picker 的人,最简单的选择是使用 UISegmentedControl.appearance()
全局设置外观。这是一个可以调用来设置外观的示例函数。
func setUISegmentControlAppearance()
UISegmentedControl.appearance().selectedSegmentTintColor = .white
UISegmentedControl.appearance().backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.1)
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.black], for: .normal)
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
但是,如果您想要具有不同设置的多个控件,则使用 UISegmentedControl.appearance()
全局设置外观选项并不是很好。另一种选择是为UISegmentedControl
实现UIViewRepresentable
。这是一个设置原始问题中询问的属性并将.apportionsSegmentWidthsByContent = true
设置为奖励的示例。希望这会为您节省一些时间...
struct MyPicker: UIViewRepresentable
@Binding var selection: Int // The type of selection may vary depending on your use case
var items: [Any]?
class Coordinator: NSObject
let parent: MyPicker
init(parent: MyPicker)
self.parent = parent
@objc func valueChanged(_ sender: UISegmentedControl)
self.parent.selection = Int(sender.selectedSegmentIndex)
func makeCoordinator() -> MyPicker.Coordinator
Coordinator(parent: self)
func makeUIView(context: Context) -> UISegmentedControl
let picker = UISegmentedControl(items: self.items)
// Any number of other UISegmentedControl settings can go here
picker.selectedSegmentTintColor = .white
picker.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.1)
picker.setTitleTextAttributes([.foregroundColor: UIColor.black], for: .normal)
picker.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
picker.apportionsSegmentWidthsByContent = true
// Make sure the coordinator updates the picker when the value changes
picker.addTarget(context.coordinator, action: #selector(Coordinator.valueChanged(_:)), for: .valueChanged)
return picker
func updateUIView(_ uiView: UISegmentedControl, context: Context)
uiView.selectedSegmentIndex = self.selection
【讨论】:
【参考方案5】:虽然上面的答案很棒,但其中大多数都将所选片段内的文本颜色弄错了。我创建了 UISegmentedControl
子类,您可以在 iOS 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
方法,我们确保每次tintColor
属性在段视图或任何底层视图上发生更改时都会调用stylize
方法,这是iOS 上的首选行为。
结果:
【讨论】:
【参考方案6】:IOS 13 和 Swift 5.0 (Xcode 11.0)Segment Control 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
【讨论】:
您是否尝试将背景设置为白色?对我来说,它是灰色的 @ItanHant 您使用的是哪种 xcode 和 swift 语言? @Ronit 当然!!我会尝试,但请告诉我现在显示什么类型的输出 swift 5,xcode 11.3!它显示了它想要的东西!不是我想要的:) @Ronit 你解决了吗?.white
也给了我灰色。【参考方案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
【讨论】:
完美!谢谢!【参考方案8】: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()!)!
【讨论】:
这是唯一对我有用的方法 - 背景图像。 selectedSegmentTintColor 由于某种原因无法正常工作。 太棒了!仍然适用于 ios 14 及更低版本 这对于摆脱默认的灰色背景颜色非常有用。 @DenNukem 获取分段色调颜色let selected = UIImage(color: .systemPink, size: CGSize(width: 1, height: 32)) UISegmentedControl.appearance().setBackgroundImage(selected, for: .selected, barMetrics: .default)
对我有用
使用 iOS 14.5,selectedSegmentTintColor
不受尊重【参考方案9】:
@Ilahi Charfeddine 的 Swift 版本回答:
if #available(iOS 13.0, *)
segmentedControl.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
segmentedControl.selectedSegmentTintColor = UIColor.blue
else
segmentedControl.tintColor = UIColor.blue
【讨论】:
【参考方案10】:您可以实现以下方法
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)
【讨论】:
【参考方案11】: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]];
【讨论】:
【参考方案12】:从 iOS 13b3 开始,UISegmentedControl
上现在有一个 selectedSegmentTintColor
。
要更改分段控件的整体颜色,请使用其backgroundColor
。
要更改所选片段的颜色,请使用selectedSegmentTintColor
。
要更改未选中段标题的颜色/字体,请使用状态为.normal
/UIControlStateNormal
的setTitleTextAttributes
。
要更改所选片段标题的颜色/字体,请使用状态为.selected
/UIControlStateSelected
的setTitleTextAttributes
。
如果您使用图像创建分段控件,如果图像被创建为模板图像,则分段控件的tintColor
将用于为图像着色。但这有一个问题。如果将tintColor
设置为与selectedSegmentTintColor
相同的颜色,则图像将不会在所选片段中可见。如果将tintColor
设置为与backgroundColor
相同的颜色,则未选中段上的图像将不可见。这意味着您的带有图像的分段控件必须使用 3 种不同的颜色才能使所有内容可见。或者您可以使用非模板图像而不设置tintColor
。
在 iOS 12 或更早版本下,只需设置分段控件的tintColor
或依赖应用的整体色调颜色即可。
【讨论】:
我们如何设置无边框的段控制器?我在 iOS 13 中没有看到这方面的设置。之前,设置 tintcolor 足以获得无边框的段控件。 请添加边框颜色等,以便大家可以找到所有与段颜色相关的问题都在这里解决。怎么说的? :) @YogeshPatel 边框颜色怎么样? iOS 13 中没有边框颜色,而在 iOS 12 中它设置为tintColor
,答案已经涵盖。
哦,那个边框。这适用于任何视图,而不仅仅是分段控件。这超出了原始问题和这个答案的范围。你的评论就够了。
我不知道为什么背景颜色在我使用 UIColor.white 时不起作用,但在我使用 UIColor.red 或其他颜色时它起作用?【参考方案13】:
从 Xcode 11 beta 3 开始
UISegmentedControl
上现在有selectedSegmentTintColor
属性。
见rmaddy's answer
恢复 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
以使所选片段的标题变为白色?
嗯,看起来应该但似乎没有。我无法访问该代码用法 atm,但左侧的图像是使用该代码创建的。
***.com/a/33675160/5790492 用于 UIImage(color:) 扩展。
如果你能添加 UIImage 扩展就很好了,这样你的答案就不是完整的 iho
@VityaShurapov 将其设置为同时突出显示 和 时,它不是传入的状态数组,而是一个选项集,这意味着将这些值组合起来创建一个新的状态。【参考方案14】:
从 Xcode 11 beta 3 开始
UISegmentedControl
上现在有selectedSegmentTintColor
属性。
谢谢@rmaddy!
原始答案,适用于 Xcode 11 beta 和 beta 2
是否有适当的解决方案,使用公共 API,不需要深入研究私有子视图结构?
在 Xcode 11.0 beta 中,按规则去做似乎是一个挑战,因为它基本上需要自己重绘每个状态的所有背景图像,包括圆角、透明度和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
此解决方案将正确地将色调颜色应用于选择,如下所示:
【讨论】:
获奖是因为时间不多了,但最好找到不涉及挖掘私有层次结构的解决方案:) @Jonathan。谢谢你。您已经获得了不涉及查看层次结构的最接近的解决方案:因为一旦您将setBackgroundImage
设置为.normal
,您就必须设置所有其他图像(包括其他状态和setDividerImage
),可能还有一些UIBezierPath
和@ 987654334@,如果我们希望以这种方式设计 iOS 13,这将变得过于复杂。
是的,理想情况下它将在测试版中修复
从 iOS 13b3 开始不再需要此功能。现在UISegmentedControl
上有selectedSegmentTintColor
属性。【参考方案15】:
这是我对 Jonathan.'s answer for Xamarin.iOS (C#) 的看法,但修复了图像大小。与 Cœur 对 Colin Blake 的回答的评论一样,我将除分隔符之外的所有图像都设为分段控件的大小。分隔线是段的 1xheight。
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://***.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;
【讨论】:
【参考方案16】:我已经尝试了解决方法,它对我很有用。这是 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
【讨论】:
我不确定它是否适用于CGRectMake(0.0f, 0.0f, 1.0f, 1.0f)
:根据我对 Xcode 11 beta 的测试,rect
的大小必须与分段控件的边界相同。
自 iOS13 beta 6 以来,tintcolor 没有显示在选定的按钮上,所以我不得不添加一行:[self setTitleTextAttributes:@NSForegroundColorAttributeName: UIColor.blackColor, NSFontAttributeName: [UIFont systemFontOfSize:13 ] forState:UIControlStateSelected];
当我尝试在[[UISegmentedControl appearance] ensureiOS12Style]
上使用它时,我得到了一个例外。知道发生了什么吗? Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSMethodSignature getArgumentTypeAtIndex:]: index (2) out of bounds [0, 1]'
以上是关于如何在 iOS 13 的 UISegmentedControl 中更改段的颜色?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 TabBar 中删除和重置顶行 - 适用于 iOS 13+
如何在 iOS 13.3 上使用 xib 显示 UITableViewCell?