【问题标题】:How can I have Image and Text for Picker in SegmentedPickerStyle in SwiftUI?如何在 SwiftUI 的 SegmentedPickerStyle 中为 Picker 提供图像和文本?
【发布时间】:2021-11-13 02:10:46
【问题描述】:

我正在使用 SwiftUI 构建一个 Picker。

现在我想为每个选择添加一个图标和文本。所以它应该看起来像这样:

这可能吗?如果是怎么办?

或者Apples苹果人机界面指南根本不推荐它?

我已经尝试使用 HStack 将图像和文本包装在一起。

enum Category: String, CaseIterable, Identifiable {
    case person
    case more

    var id: String { self.rawValue }
}

struct ContentView: View {

    @State private var category = Category.person

    var body: some View {
        Picker("Category", selection: $category) {
            HStack {
                Image(systemName: "person")
                Text("Person")
            }.tag(Category.person)
            HStack {
                Image(systemName: "ellipsis.circle")
                Text("More")
            }.tag(Category.more)
        }.pickerStyle(SegmentedPickerStyle())
        .padding()
    }
}

但框架将其分成四部分。

【问题讨论】:

  • 如果没有Minimal Reproducible Example,就无法帮助您解决已尝试的问题。
  • 似乎没有一种简单的方法可以做到这一点。无论如何,您不应该在此处真正混合图像+文本,它应该是其中之一,但不能两者兼而有之。
  • 谁说这个问题应该被关闭?为什么?!
  • 这似乎是一个简单的问题:只需放一个Label 而不是HStack... 但它不起作用?!我也尝试使用自定义 LabelStyle... 但没有成功。似乎SegmentedPickerStyle 只使用提供的两个视图之一。选择 WheelPickerStyle 将按预期显示标签。这绝对是分段选择器的问题。
  • 根据Apple Human Interface Guidelines for segmented controls,绝对不希望同时拥有文本和图像。所以这不是 SwiftUI 的错误,而是一个特性:你不能做错:-)

标签: swiftui picker


【解决方案1】:

您可以制作自定义 Picker

struct ContentView: View {
var body: some View {
    Home()
}
}

struct Home: View {

@State var index = 0
var body: some View {
    
    VStack {
        HStack {
            Text("Picker with icon")
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(.black)
            Spacer(minLength: 0)
        }
        .padding(.horizontal)
        
        
        HStack(spacing: 0){
            HStack{
                Image(systemName: "person")
                    .foregroundColor(self.index == 0 ? .black : .gray)
                Text("Person")
                    .foregroundColor(self.index == 0 ? .black : .gray)
                
                
            }
            .padding(.vertical, 10)
            .padding(.horizontal, 35)
            .background((Color.white).opacity(self.index == 0 ? 1 : 0))
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 0
            }
            
            HStack{
                Image(systemName: "ellipsis.circle")
                    .foregroundColor(self.index == 1 ? .black : .gray)
                Text("More")
                    .foregroundColor(self.index == 1 ? .black : .gray)
                
                
            }
            .padding(.vertical, 10)
            .padding(.horizontal, 35)
            .background((Color.white).opacity(self.index == 1 ? 1 : 0))
            .clipShape(Capsule())
            .onTapGesture {
                self.index = 1
            }
        }
        .padding(3)
        .background(Color.black.opacity(0.06))
        .clipShape(Capsule())
        Spacer(minLength: 0)
    }
    .padding(.top)
}

}

【讨论】:

    【解决方案2】:

    这是一种将 Apple Picker 用于您想要的输出的方法:

    enum Category: String, CaseIterable, Identifiable {
        case person
        case more
        
        var id: String { self.rawValue }
    }
    
    
    struct ContentView: View {
        
        @State private var category = Category.person
        
        private var view1: some View { HStack { Image(systemName: "person"); Text("Person") } }
        private var view2: some View { HStack { Image(systemName: "ellipsis.circle"); Text("More") } }
        
        @State private var uiImage1: UIImage? = nil
        @State private var uiImage2: UIImage? = nil
        
        var body: some View {
            
            return Picker("Category", selection: $category) {
                
                if let unwrappedUIImage1 = uiImage1 {
                    Image(uiImage: unwrappedUIImage1)
                        .tag(Category.person)
                    
                }
                
                if let unwrappedUIImage2 = uiImage2 {
                    Image(uiImage: unwrappedUIImage2)
                        .tag(Category.more)
                    
                }
                
            }
            .pickerStyle(SegmentedPickerStyle())
            .padding()
            .onAppear() {
                
                DispatchQueue.main.async {
                    uiImage1 = viewToUIImageConverter(content: view1)
                    uiImage2 = viewToUIImageConverter(content: view2)
                }
                
                print("Your selection is:", category.rawValue)
            }
            .onChange(of: category, perform: { newValue in print("Your selection is:", newValue.rawValue) })
            
        }
    }
    
    
    
    func viewToUIImageConverter<Content: View>(content: Content) -> UIImage? {
        
        let controller = UIHostingController(rootView: content)
        let view = controller.view
        
        let targetSize = controller.view.intrinsicContentSize
        
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = UIColor.clear
        
        let renderer = UIGraphicsImageRenderer(size: targetSize)
        
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
        
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 2023-01-28
      • 1970-01-01
      相关资源
      最近更新 更多