繁体   English   中英

如何在 SwiftUI Segmented Picker 中更改选定的段颜色

[英]How to change selected segment color in SwiftUI Segmented Picker

我想在 SwiftUI 分段选择器中设置选定的分段颜色并将文本颜色更改为白色。

我已经尝试过使用选择器视图的修饰符和修改外观代理的色调。 不幸的是,它们似乎都不起作用。


import SwiftUI

struct PickerView: View {

    @State var pickerSelection = 0

    init() {
        UISegmentedControl.appearance().tintColor = UIColor.blue
    }

    var body: some View {
        Picker(selection: $pickerSelection, label: Text("")) {
            Text("Active").tag(0).foregroundColor(Color.white)
            Text("Completed").tag(1)
        }.pickerStyle(SegmentedPickerStyle()).foregroundColor(Color.orange)
    }
}

在 SwiftUI 中有什么方法可以做到这一点,还是我应该通过使用 UIViewControllerRepresentable 来使用 UISegmentedControl?

本机(但有限

SwiftUI 目前不支持本机 SegmentedPicker 样式(有关工作解决方法,请参阅答案的底部)。 但是使用.colorMultiply()修饰符将颜色应用于分段选择器的方法是有限的:

在此处输入图像描述


使用UIAppearance完全控制

selectedSegmentTintColor自 beta 3 起可用于更改选定段的颜色。

要更改textColor ,您应该将setTitleTextAttributes用于.selected状态和.normal状态(未选中)。

所以它会像:

init() {
    UISegmentedControl.appearance().selectedSegmentTintColor = .blue
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.blue], for: .normal)
}

分段控制

同样正如迈克所提到的,您也可以设置背景颜色,例如:

UISegmentedControl.appearance().backgroundColor = .yellow

后台演示

另外,别忘了你也可以设置 SwiftUI 颜色! 例如:

UISegmentedControl.appearance().selectedSegmentTintColor = UIColor(Color.accentColor)

最近我遇到了一个类似的问题,我需要为SwiftUI SegmentedControl自定义backgroundforeground 。我发现这篇文章也很有帮助,但我也想分享我现在正在使用的其他解决方案。 有一个非常不错的包叫做SwiftUI Introspect ,它允许...

SwiftUI内省底层 UIKit 组件

有了这个包,我创建了以下SegmentedControl 在此处输入图像描述 使用此代码:

VStack {
    Picker("Activity view", selection: $selectedActivity) {
        ForEach(ActivityView.allCases) { activity in
            Text(activity.description)
        }
    }
    .introspectSegmentedControl { segmentedControl in
        segmentedControl.backgroundColor = .clear
        segmentedControl.tintColor = TCHColors.SegmentedControl.backgroundSelected
        segmentedControl.selectedSegmentTintColor = TCHColors.SegmentedControl.backgroundSelected
        segmentedControl.setTitleTextAttributes([
            NSAttributedString.Key.foregroundColor: TCHColors.SegmentedControl.selectedText
        ], for: .selected)
        segmentedControl.setTitleTextAttributes([
            NSAttributedString.Key.foregroundColor: TCHColors.SegmentedControl.normalText
        ], for: .normal)
    }
    .pickerStyle(.segmented)
}
.padding(.horizontal, 16)

您可以使用这个包从 SwiftUI 访问许多其他底层组件。

这个回答对我有帮助,但我想补充一点。 我使用的颜色是视图的参数,因此将这些方法放在 init 中不允许我访问颜色。

或者,您可以直接在分段选取器上使用onAppear方法,如下所示。

import SwiftUI

struct PickerView: View {
    var color: UIColor   
    @State var pickerSelection = 0

    var body: some View {
        Picker(selection: $pickerSelection, label: Text("")) {
            Text("Active").tag(0).foregroundColor(Color.white)
            Text("Completed").tag(1)
        }.pickerStyle(SegmentedPickerStyle()).foregroundColor(Color.orange)
        .onAppear {
            UISegmentedControl.appearance().tintColor = color
        }
    }
}

🔴 不幸的是,没有 SwiftUI 原生的方法来更改分段控件的默认颜色。 让我们覆盖默认颜色的解决方案是更改 UISegmentedControl 的外观,就像我们在基于 UIKit 的应用程序中所做的那样。

🔴 为了实现这一点,有必要明确定义我们正在处理的视图的init()方法:

struct ContentView: View {

init() {
        
    }

 ...
}

🔴 在init()主体中,我们将指定选定段的色调颜色、正常状态下的文本颜色和选定状态下的文本颜色。 以下是所有操作的完成方式:

init() {
    UISegmentedControl.appearance().selectedSegmentTintColor = .systemIndigo
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.systemYellow], for: .normal)
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
}

🔴 上面代码的结果如下图所示:

在此处输入图像描述

完成😊

这是分段选择器功能的手动实现:

@ViewBuilder func viewSegmentedButtons(arr: [String], selIndex: Int, baseColor: Color, closure:@escaping (_ selectedIndex: Int) -> Void) -> some View {
    
    let columns = Array(repeating: GridItem(spacing: 1), count:arr.count)
    LazyVGrid(columns: columns, spacing: 1.0) {
        ForEach(Array(arr.enumerated()), id: \.element) { index, translation in
            Button {
                closure(index)
            } label: {
                ZStack {
                    Rectangle()
                        .foregroundColor(index == selIndex ? baseColor : Color(.systemBackground))
                        .cornerRadius(radius: index==0 ? cRadius : 0, corners: [.topLeft, .bottomLeft])
                        .cornerRadius(radius: index==arr.count-1 ? cRadius : 0, corners: [.topRight, .bottomRight])
                    Text(translation)
                        .padding(.vertical, 10)
                        .font(.footnote)
                        .foregroundColor(index != selIndex ? baseColor : Color(.systemBackground) )
                }
            }
        }
    }
    .foregroundColor(baseColor)
    .overlay(
        RoundedRectangle(cornerRadius: cRadius)
            .stroke(baseColor, lineWidth: 2)
    )
    .font(.callout)
    .background(baseColor)
    .cornerRadius(cRadius)
    .padding(.bottom, 10)
}

使用示例:

@State private var levelIndex: Int = 0
var body: some View {
    VStack {
        Text("Level:")
        
        viewSegmentedButtons(arr: ["Easy", "Meduim", "Hard"], selIndex: levelIndex, baseColor: .orange) { selectedIndex in
            withAnimation {
                levelIndex = selectedIndex
            }
        }
    }
}

结果: 在此处输入图像描述

这是我在 SwiftUI 中工作的解决方案:

init(){

    UISegmentedControl.appearance().selectedSegmentTintColor = .green
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.black], for: .selected)

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM