A UISegmentedControl
在iOS 13中具有新外观,并且现有代码更改分段控件的颜色不再像以前那样起作用。
在iOS 13之前,您可以设置tintColor
和,以用于分段控件周围的边框,分段之间的线条以及所选分段的背景颜色。然后,您可以使用带有的前景色属性更改每个句段标题的颜色titleTextAttributes
。
在iOS 13下,tintColor
什么都不做。您可以设置分段控件backgroundColor
以更改分段控件的整体颜色。但是我找不到任何方法来更改用作所选段背景的颜色。设置文本属性仍然有效。我什至尝试设置标题的背景色,但这只会影响标题的背景,而不会影响所选片段的其余背景色。
简而言之,您如何修改UISegmentedControl
iOS 13中当前选定的段的背景颜色?是否有使用公共API的适当解决方案,而无需深入研究私有子视图结构?
在iOS 13中,没有针对UISegmentedControl
或的新属性,UIControl
并且这些更改UIView
均不相关。
1> rmaddy..:
由于iOS的13B3的,现在有一个selectedSegmentTintColor
上UISegmentedControl
。
要更改分段控件的整体颜色,请使用backgroundColor
。
要更改所选段的颜色,请使用selectedSegmentTintColor
。
要更改未选择的段标题的颜色/字体,请使用/ setTitleTextAttributes
状态。.normal
UIControlStateNormal
要更改所选段标题的颜色/字体,请使用/ setTitleTextAttributes
状态。.selected
UIControlStateSelected
如果使用图像创建分段控件,则将图像创建为模板图像时,tintColor
将使用分段控件为图像着色。但这有一个问题。如果将设置tintColor
为与相同的颜色,selectedSegmentTintColor
则图像将在所选段中不可见。如果将设置tintColor
为与相同的颜色backgroundColor
,则未选择的线段上的图像将不可见。这意味着您的带有图像的分段控件必须使用3种不同的颜色才能使所有内容可见。或者,您可以使用非模板图像而不设置tintColor
。
在iOS 12或更早版本下,只需设置细分控件tintColor
或依靠应用程序的整体色彩即可。
2> Jonathan...:
从Xcode 11 beta 3开始
现在有selectedSegmentTintColor
物业UISegmentedControl
。
查看rmaddy的答案
重新获得iOS 12外观
我无法为所选部分着色,希望它会在即将发布的Beta版中得到修复。
如果不设置正常状态的背景图像,则设置选定状态的背景图像将不起作用(这将删除所有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
}
}
}
/sf/ask/17360801/用于UIImage(color :)扩展。
3> Cœur..:
从Xcode 11 beta 3开始
现在有selectedSegmentTintColor
物业UISegmentedControl
。
谢谢@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
}
}
}
}
}
此解决方案将正确地将色调颜色应用于所选内容,如下所示:
从iOS 13b3开始不再需要此功能。现在,UISegmentedControl上具有selectedSegmentTintColor属性。
4> Ilahi Charfe..:
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]];}
5> 小智..:
我已经尝试了解决方法,对我来说效果很好。这是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
6> Vignan S..:
@Ilahi Charfeddine的Swift版本答案:
if #available(iOS 13.0, *) {
segmentedControl.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
segmentedControl.selectedSegmentTintColor = UIColor.blue
} else {
segmentedControl.tintColor = UIColor.blue
}
7> 小智..:
IOS 13和Swift 5.0(Xcode 11.0)Segment Control 100%Working
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
}