如何为单个段设置 UISegmentedControl Tint Color
How to set UISegmentedControl Tint Color for individual segment
开始学习 Swift 并尝试转换此 ObjectiveC 代码:
[[mySegmentedControl.subviews objectAtIndex:0] setTintColor:[UIColor blueColor]]
这正确设置了第一段的色调。
这是我最接近获得相同代码的 Swift 版本的版本:
mySegmentedControl?.subviews[0].tintColor = UIColor.blueColor()
我得到的错误是'@Ivalue $T9' is not identical to 'UIColor!!'
我不明白这个错误是什么意思。当我查看 .tintColor
方法时,它列出了 UIColor!?
,但我还没有找到 !?
在 Swift 中的含义。
这将解决您的问题:
var subViewOfSegment: UIView = mySegmentedControl.subviews[0] as UIView
subViewOfSegment.tintColor = UIColor.blueColor()
你也可以
(mySegmentedControl.subviews[0] as UIView).tintColor = UIColor .blueColor()
用于更改所选段的 tintColor
使用 UISegmentControl 的值更改事件按其原始 x 值对段进行排序,然后循环并比较 selectedSegmentIndex 属性。这是一个假设 4 段的分段控制的示例:
@IBAction func indexChanged(sender: UISegmentedControl) {
let sortedViews = sender.subviews.sort( { [=10=].frame.origin.x < .frame.origin.x } )
for (index, view) in sortedViews.enumerate() {
if index == sender.selectedSegmentIndex {
view.tintColor = UIColor.blueColor()
} else {
view.tintColor = UIColor.lightGrayColor()
}
}
}
然后在 viewDidLoad 中为最初选择的段设置 tintColor,在本例中它是第一个:
let sortedViews = segmentedControlOutletVariable.subviews.sort( { [=11=].frame.origin.x < .frame.origin.x } )
sortedViews[0].tintColor = UIColor.blueColor()
我找到的最简单的方法是:
segmentControl.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.redColor()], forState: UIControlState.Selected)
class MyUISegmentedControl: UISegmentedControl {
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)!
for subViewOfSegment: UIView in subviews {
subViewOfSegment.tintColor = UIColor.red
}
}
}
此代码适用于 2019 年 8 月最新版本的 Swift (Swift 3.0)
这里我实现的这段代码是Segment控件的扩展,可以用于应用程序中的所有Segment控件,其中代码集必须在应用程序中定义class.
扩展方法可以直接在应用程序中使用,也可以将所有设置添加到扩展中的相同方法或不同方法class,如下所示。
extension UISegmentedControl {
func setSegmentStyle() {
setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
let segAttributes: NSDictionary = [
NSForegroundColorAttributeName: UIColor.gray,
NSFontAttributeName: UIFont(name: "System-System", size: 14)!
]
setTitleTextAttributes(segAttributes as [NSObject : AnyObject], for: UIControlState.selected)
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
可以在任何地方使用以下代码
self.mySegment.setSegmentStyle()
在对这个问题和其他类似问题进行分析并尝试了很多答案之后,我意识到使用第 3 方自定义分段控件进行自定义比尝试破解 Apple 的 UISegmentedControl 更容易和更安全。
这是一个使用 XMSegmentedControl (Swift 3) 进行自定义的示例。
部分代码:
mySegmentControl.delegate = self
mySegmentControl.font = UIFont.systemFont(ofSize: 12)
还有一些在 Interface Builder 中(如果需要,也可以在代码中完成):
结果是:
在我的例子中,它看起来非常像系统一,但仍然存在细微差别,我必须完全按照设计师的要求去做。
请注意,XMSegmentedControl 不允许不同的段使用不同的背景颜色,但如果需要,您可以轻松添加它,因为它是一个简单的 .swift 文件,非常容易理解和修改.
sender.subviews.sort
在 Swift 4 中不起作用,删除边框在
中被引用
extension UISegmentedControl {
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
func removeBackgroundColors() {
self.setBackgroundImage(imageWithColor(color: .clear), for: .normal, barMetrics: .default)
self.setBackgroundImage(imageWithColor(color: .clear), for: .selected, barMetrics: .default)
self.setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
struct viewPosition {
let originX: CGFloat
let originIndex: Int
}
func updateTintColor(selected: UIColor, normal: UIColor) {
let views = self.subviews
var positions = [viewPosition]()
for (i, view) in views.enumerated() {
let position = viewPosition(originX: view.frame.origin.x, originIndex: i)
positions.append(position)
}
positions.sort(by: { [=10=].originX < .originX })
for (i, position) in positions.enumerated() {
let view = self.subviews[position.originIndex]
if i == self.selectedSegmentIndex {
view.tintColor = selected
} else {
view.tintColor = normal
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
mySegment.removeBackgroundColors()
mySegment.backgroundColor = .clear
mySegment.updateTintColor(selected: myNavigationColor, normal: text1Color)
}
该解决方案仅适用于两个细分市场,但可以轻松扩展以根据需要使用。
首先,我建议创建一个枚举:
enum SegmentedSections: Int {
case first,
case second
}
然后创建一个函数,并在viewDidLoad中调用这个函数,并且每次在segmentedControl中发生.valueChanged时调用它:
func setProperSegmentedControlColoring(_ segment: UISegmentedControl, type: SegmentedSections) {
setSeparatorImages(for: segment, with: type)
let subviews = segment.subviews
let sortedViews = subviews.sorted(by: { [=11=].frame.origin.x < .frame.origin.x })
for (index, view) in sortedViews.enumerated() {
switch type {
case .first:
if index == segment.selectedSegmentIndex {
view.tintColor = .red
} else {
view.tintColor = .blue
}
case .second:
if index == segment.selectedSegmentIndex {
view.tintColor = .blue
} else {
view.tintColor = .red
}
}
}
}
此外,您还需要相应地更改分隔图像:
func setSeparatorImages(for segment: UISegmentedControl, with type: EarnType) {
switch type {
case .first:
let image = UIImage(color: .red)
segment.setDividerImage(image, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
case .second:
let image = UIImage(color: .blue)
segment.setDividerImage(image, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
}
}
此外,您还需要 UIImage 的扩展。 You can find it here.
对于 Swift 5.1,我发现可以工作:
//To set Text Colour when Segment Selected
segmentOutlet.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: UIControl.State.selected)
//To Set Background Colour when Segment Selected,
//The number in the [] is the segment that gets value change
let subViewOfSegment: UIView = segmentOutlet.subviews[1] as UIView
subViewOfSegment.backgroundColor = UIColor.blue
我将它们放在 Switch 语句中,用于在按下时捕获按钮的动作。
从iOS13开始,属性selectedSegmentTintColor
可以用来设置段控件的tint颜色!
所以简单地做:
segmentControl.selectedSegmentTintColor = .red
如果支持以下iOS13,
if #available(iOS 13.0, *) {
segmentControl.selectedSegmentTintColor = .red
} else {
// Fallback on earlier versions
// Solution posted by David can be used here
}
开始学习 Swift 并尝试转换此 ObjectiveC 代码:
[[mySegmentedControl.subviews objectAtIndex:0] setTintColor:[UIColor blueColor]]
这正确设置了第一段的色调。
这是我最接近获得相同代码的 Swift 版本的版本:
mySegmentedControl?.subviews[0].tintColor = UIColor.blueColor()
我得到的错误是'@Ivalue $T9' is not identical to 'UIColor!!'
我不明白这个错误是什么意思。当我查看 .tintColor
方法时,它列出了 UIColor!?
,但我还没有找到 !?
在 Swift 中的含义。
这将解决您的问题:
var subViewOfSegment: UIView = mySegmentedControl.subviews[0] as UIView
subViewOfSegment.tintColor = UIColor.blueColor()
你也可以
(mySegmentedControl.subviews[0] as UIView).tintColor = UIColor .blueColor()
用于更改所选段的 tintColor
使用 UISegmentControl 的值更改事件按其原始 x 值对段进行排序,然后循环并比较 selectedSegmentIndex 属性。这是一个假设 4 段的分段控制的示例:
@IBAction func indexChanged(sender: UISegmentedControl) {
let sortedViews = sender.subviews.sort( { [=10=].frame.origin.x < .frame.origin.x } )
for (index, view) in sortedViews.enumerate() {
if index == sender.selectedSegmentIndex {
view.tintColor = UIColor.blueColor()
} else {
view.tintColor = UIColor.lightGrayColor()
}
}
}
然后在 viewDidLoad 中为最初选择的段设置 tintColor,在本例中它是第一个:
let sortedViews = segmentedControlOutletVariable.subviews.sort( { [=11=].frame.origin.x < .frame.origin.x } )
sortedViews[0].tintColor = UIColor.blueColor()
我找到的最简单的方法是:
segmentControl.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.redColor()], forState: UIControlState.Selected)
class MyUISegmentedControl: UISegmentedControl {
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)!
for subViewOfSegment: UIView in subviews {
subViewOfSegment.tintColor = UIColor.red
}
}
}
此代码适用于 2019 年 8 月最新版本的 Swift (Swift 3.0)
这里我实现的这段代码是Segment控件的扩展,可以用于应用程序中的所有Segment控件,其中代码集必须在应用程序中定义class.
扩展方法可以直接在应用程序中使用,也可以将所有设置添加到扩展中的相同方法或不同方法class,如下所示。
extension UISegmentedControl {
func setSegmentStyle() {
setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
let segAttributes: NSDictionary = [
NSForegroundColorAttributeName: UIColor.gray,
NSFontAttributeName: UIFont(name: "System-System", size: 14)!
]
setTitleTextAttributes(segAttributes as [NSObject : AnyObject], for: UIControlState.selected)
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
可以在任何地方使用以下代码
self.mySegment.setSegmentStyle()
在对这个问题和其他类似问题进行分析并尝试了很多答案之后,我意识到使用第 3 方自定义分段控件进行自定义比尝试破解 Apple 的 UISegmentedControl 更容易和更安全。
这是一个使用 XMSegmentedControl (Swift 3) 进行自定义的示例。
部分代码:
mySegmentControl.delegate = self
mySegmentControl.font = UIFont.systemFont(ofSize: 12)
还有一些在 Interface Builder 中(如果需要,也可以在代码中完成):
结果是:
在我的例子中,它看起来非常像系统一,但仍然存在细微差别,我必须完全按照设计师的要求去做。
请注意,XMSegmentedControl 不允许不同的段使用不同的背景颜色,但如果需要,您可以轻松添加它,因为它是一个简单的 .swift 文件,非常容易理解和修改.
sender.subviews.sort
在 Swift 4 中不起作用,删除边框在
extension UISegmentedControl {
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
func removeBackgroundColors() {
self.setBackgroundImage(imageWithColor(color: .clear), for: .normal, barMetrics: .default)
self.setBackgroundImage(imageWithColor(color: .clear), for: .selected, barMetrics: .default)
self.setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
struct viewPosition {
let originX: CGFloat
let originIndex: Int
}
func updateTintColor(selected: UIColor, normal: UIColor) {
let views = self.subviews
var positions = [viewPosition]()
for (i, view) in views.enumerated() {
let position = viewPosition(originX: view.frame.origin.x, originIndex: i)
positions.append(position)
}
positions.sort(by: { [=10=].originX < .originX })
for (i, position) in positions.enumerated() {
let view = self.subviews[position.originIndex]
if i == self.selectedSegmentIndex {
view.tintColor = selected
} else {
view.tintColor = normal
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
mySegment.removeBackgroundColors()
mySegment.backgroundColor = .clear
mySegment.updateTintColor(selected: myNavigationColor, normal: text1Color)
}
该解决方案仅适用于两个细分市场,但可以轻松扩展以根据需要使用。 首先,我建议创建一个枚举:
enum SegmentedSections: Int {
case first,
case second
}
然后创建一个函数,并在viewDidLoad中调用这个函数,并且每次在segmentedControl中发生.valueChanged时调用它:
func setProperSegmentedControlColoring(_ segment: UISegmentedControl, type: SegmentedSections) {
setSeparatorImages(for: segment, with: type)
let subviews = segment.subviews
let sortedViews = subviews.sorted(by: { [=11=].frame.origin.x < .frame.origin.x })
for (index, view) in sortedViews.enumerated() {
switch type {
case .first:
if index == segment.selectedSegmentIndex {
view.tintColor = .red
} else {
view.tintColor = .blue
}
case .second:
if index == segment.selectedSegmentIndex {
view.tintColor = .blue
} else {
view.tintColor = .red
}
}
}
}
此外,您还需要相应地更改分隔图像:
func setSeparatorImages(for segment: UISegmentedControl, with type: EarnType) {
switch type {
case .first:
let image = UIImage(color: .red)
segment.setDividerImage(image, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
case .second:
let image = UIImage(color: .blue)
segment.setDividerImage(image, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
}
}
此外,您还需要 UIImage 的扩展。 You can find it here.
对于 Swift 5.1,我发现可以工作:
//To set Text Colour when Segment Selected
segmentOutlet.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: UIControl.State.selected)
//To Set Background Colour when Segment Selected,
//The number in the [] is the segment that gets value change
let subViewOfSegment: UIView = segmentOutlet.subviews[1] as UIView
subViewOfSegment.backgroundColor = UIColor.blue
我将它们放在 Switch 语句中,用于在按下时捕获按钮的动作。
从iOS13开始,属性selectedSegmentTintColor
可以用来设置段控件的tint颜色!
所以简单地做:
segmentControl.selectedSegmentTintColor = .red
如果支持以下iOS13,
if #available(iOS 13.0, *) {
segmentControl.selectedSegmentTintColor = .red
} else {
// Fallback on earlier versions
// Solution posted by David can be used here
}