SwiftUI 自定义选择器样式 [英] SwiftUI Custom PickerStyle

查看:49
本文介绍了SwiftUI 自定义选择器样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个类似于 SegmentedPickerStyle() 的自定义 PickerStyle.这是我目前的状态:

导入 SwiftUI公共结构 FilterPickerStyle: PickerStyle {public static func _makeView(值:_GraphValue<_PickerValue,输入:_ViewInputs)->_ViewOutputs where SelectionValue : Hashable {}public static func _makeViewList(值:_GraphValue<_PickerValue,输入:_ViewListInputs)->_ViewListOutputs where SelectionValue : Hashable {}}

我创建了一个符合 PickerStyle 协议的结构体.Xcode然后添加了所需的协议方法,但我不知道如何使用它们.有人能解释一下如何处理这些方法吗,例如,如果我想实现类似于 SegmentedPickerStyle() 的东西?

解决方案

由于其他东西出现,我还没有完成它,但这是我的(未完成的尝试实现 SegmentedPicker):

<预><代码>struct SegmentedPickerElementView:查看其中内容:查看{@Binding var selectedElement: Int让内容:() ->内容@inlinable init(_ selectedElement: Binding, @ViewBuilder content: @escaping() -> Content) {self._selectedElement = selectedElementself.content = 内容}var主体:一些视图{GeometryReader { 代理输入自我内容().fixedSize(水平:真,垂直:真).frame(minWidth: proxy.size.width, minHeight: proxy.size.height).contentShape(矩形())}}}struct SegmentedPickerView:查看{@Environment (\.colorScheme) var colorScheme: ColorSchemevar 元素: [(id: Int, view: AnyView)]@Binding var selectedElement: Int@State var internalSelectedElement: Int = 0私有变量宽度:CGFloat = 620私有变量高度:CGFloat = 200私有变量角半径:CGFloat = 20私有变量因子:CGFloat = 0.95私有变量颜色 = 颜色(UIColor.systemGray)私有 var selectedColor = Color(UIColor.systemGray2)init(_ selectedElement: Binding) {self._selectedElement = selectedElementself.elements = [(id: 0, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(4").字体(.系统(.标题))})),(id: 1, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(5").字体(.系统(.标题))})),(id: 2, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(9").字体(.系统(.标题))})),(id: 3, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(13").字体(.系统(.标题))})),(id: 4, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(13").字体(.系统(.标题))})),(id: 5, 视图: AnyView(SegmentedPickerElementView(selectedElement) {文本(13").字体(.系统(.标题))})),]self.internalSelectedElement = selectedElement.wrappedValue}func calcXPosition() ->CGFloat {var pos = CGFloat(-self.width * self.factor/2.4)pos += CGFloat(self.internalSelectedElement) * self.width * self.factor/CGFloat(self.elements.count)返回位置}var主体:一些视图{ZStack {长方形().foregroundColor(self.selectedColor).cornerRadius(self.cornerRadius * self.factor).frame(width: self.width * self.factor/CGFloat(self.elements.count), height: self.height - self.width * (1 - self.factor)).offset(x: calcXPosition()).animation(.easeInOut(duration: 0.2))HStack(对齐:.center,间距:0){ForEach(self.elements, id: \.id) { item initem.view.gesture(TapGesture().onEnded { _ in打印(item.id)self.selectedElement = item.id带动画{self.internalSelectedElement = item.id}})}}}.frame(宽度:self.width,高度:self.height).background(self.color).cornerRadius(self.cornerRadius).填充()}}struct SegmentedPickerView_Previews: PreviewProvider {静态 var 预览:一些视图 {SegmentedPickerView(.constant(1))}}

我还没有弄清楚值 2.4 所在的公式......这取决于元素的数量......她是我学到的:

2 个元素 = 4

3 个元素 = 3

4 个元素 = 2.6666

5 个元素 = ca.2.4

如果你弄清楚并修复了选择器中内容的对齐方式,它基本上是完全可调的......你也可以传递孔的widthheight事物矿石使用 GeometryReader

祝你好运!

P.S.:我会在完成后更新它,但目前这不是我的第一要务,所以不要指望我会这样做.

I'm trying to write a custom PickerStyle that looks similar to the SegmentedPickerStyle(). This is my current status:

import SwiftUI

public struct FilterPickerStyle: PickerStyle {
    public static func _makeView<SelectionValue>(value: _GraphValue<_PickerValue<FilterPickerStyle, SelectionValue>>, inputs: _ViewInputs) -> _ViewOutputs where SelectionValue : Hashable {

    }

    public static func _makeViewList<SelectionValue>(value: _GraphValue<_PickerValue<FilterPickerStyle, SelectionValue>>, inputs: _ViewListInputs) -> _ViewListOutputs where SelectionValue : Hashable {

    }
}

I created a struct that conforms to the PickerStyle protocol. Xcode then added the required protocol methods, but I don't know how to use them. Could someone explain how to deal with these methods, if I for example want to achieve something similar to the SegmentedPickerStyle()?

解决方案

I haven't finished it yet since other stuff came up, but here is my (unfinished attempt to implement a SegmentedPicker):


struct SegmentedPickerElementView<Content>: View where Content : View {
    @Binding var selectedElement: Int
    let content: () -> Content

    @inlinable init(_ selectedElement: Binding<Int>, @ViewBuilder content: @escaping () -> Content) {
        self._selectedElement = selectedElement
        self.content = content
    }

    var body: some View {
        GeometryReader { proxy in
            self.content()
                .fixedSize(horizontal: true, vertical: true)
                .frame(minWidth: proxy.size.width, minHeight: proxy.size.height)
                .contentShape(Rectangle())
        }
    }

}

struct SegmentedPickerView: View {
    @Environment (\.colorScheme) var colorScheme: ColorScheme

    var elements: [(id: Int, view: AnyView)]

    @Binding var selectedElement: Int
    @State var internalSelectedElement: Int = 0

    private var width: CGFloat = 620
    private var height: CGFloat = 200
    private var cornerRadius: CGFloat = 20
    private var factor: CGFloat = 0.95

    private var color = Color(UIColor.systemGray)
    private var selectedColor = Color(UIColor.systemGray2)


    init(_ selectedElement: Binding<Int>) {
        self._selectedElement = selectedElement
        self.elements = [
            (id: 0, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("4").font(.system(.title))
            })),
            (id: 1, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("5").font(.system(.title))

            })),
            (id: 2, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("9").font(.system(.title))

            })),
            (id: 3, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("13").font(.system(.title))

            })),
            (id: 4, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("13").font(.system(.title))

            })),
            (id: 5, view: AnyView(SegmentedPickerElementView(selectedElement) {
                Text("13").font(.system(.title))

            })),
        ]
        self.internalSelectedElement = selectedElement.wrappedValue
    }

    func calcXPosition() -> CGFloat {
        var pos = CGFloat(-self.width * self.factor / 2.4)
        pos += CGFloat(self.internalSelectedElement) * self.width * self.factor / CGFloat(self.elements.count)
        return pos
    }

    var body: some View {
        ZStack {
            Rectangle()
                .foregroundColor(self.selectedColor)
                .cornerRadius(self.cornerRadius * self.factor)
                .frame(width: self.width * self.factor / CGFloat(self.elements.count), height: self.height - self.width * (1 - self.factor))
                .offset(x: calcXPosition())
                .animation(.easeInOut(duration: 0.2))

            HStack(alignment: .center, spacing: 0) {
                ForEach(self.elements, id: \.id) { item in
                    item.view
                        .gesture(TapGesture().onEnded { _ in
                            print(item.id)
                            self.selectedElement = item.id
                            withAnimation {
                                self.internalSelectedElement = item.id
                            }
                        })
                }
            }
        }
        .frame(width: self.width, height: self.height)
        .background(self.color)
        .cornerRadius(self.cornerRadius)
        .padding()
    }
}

struct SegmentedPickerView_Previews: PreviewProvider {
    static var previews: some View {
        SegmentedPickerView(.constant(1))
    }
}

I haven't figured out the formula where the value 2.4 sits... it depends on the number of elements... her is what I have learned:

2 Elements = 4

3 Elements = 3

4 Elements = 2.6666

5 Elements = ca. 2.4

If you figure that out and fix the alignment of the content in the pickers its basically fully adjustable ... you could also pass the width and height of the hole thing ore use GeometryReader

Good Luck!

P.S.: I will update this when its finished but at the moment it is not my number one priority so don't expect me to do so.

这篇关于SwiftUI 自定义选择器样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆