SwiftUI - Полумодальный? - PullRequest
       19

SwiftUI - Полумодальный?

5 голосов
/ 21 июня 2019

Я пытаюсь воссоздать модал так же, как Safari в iOS13 в SwiftUI:

Вот как это выглядит:

enter image description here

Кто-нибудь знает, возможно ли это в SwiftUI ? Я хочу показать небольшую половину модальной модели с возможностью перетаскивания в полноэкранный режим, как лист обмена.

Любой совет очень ценится!

Ответы [ 2 ]

2 голосов
/ 02 июля 2019

Начиная с Beta 2 Beta 3, вы не можете представить модальное View как .fullScreen.Он представлен как .automatic -> .pageSheet.Но даже если это исправить, я сильно сомневаюсь, что они дадут вам возможность перетаскивания там бесплатно.Он уже будет включен в документы.

Вы можете использовать этот ответ , чтобы представить полный экран на данный момент. Суть здесь .

Затем, после презентации, это быстрый и грязный пример того, как вы можете воссоздать это взаимодействие.

    @State var drag: CGFloat = 0.0

    var body: some View {
        ZStack(alignment: .bottom) {
            Spacer() // Use the full space
            Color.red
                .frame(maxHeight: 300 + self.drag) // Whatever minimum height you want, plus the drag offset
                .gesture(
                    DragGesture(coordinateSpace: .global) // if you use .local the frame will jump around
                        .onChanged({ (value) in
                            self.drag = max(0, -value.translation.height)
                        })
                )
        }
    }
1 голос
/ 11 июля 2019

Вы можете сделать свой собственный и поместить его в zstack: https://www.mozzafiller.com/posts/swiftui-slide-over-card-like-maps-stocks

struct SlideOverCard<Content: View> : View {
    @GestureState private var dragState = DragState.inactive
    @State var position = CardPosition.top

    var content: () -> Content
    var body: some View {
        let drag = DragGesture()
            .updating($dragState) { drag, state, transaction in
                state = .dragging(translation: drag.translation)
            }
            .onEnded(onDragEnded)

        return Group {
            Handle()
            self.content()
        }
        .frame(height: UIScreen.main.bounds.height)
        .background(Color.white)
        .cornerRadius(10.0)
        .shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
        .offset(y: self.position.rawValue + self.dragState.translation.height)
        .animation(self.dragState.isDragging ? nil : .spring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
        .gesture(drag)
    }

    private func onDragEnded(drag: DragGesture.Value) {
        let verticalDirection = drag.predictedEndLocation.y - drag.location.y
        let cardTopEdgeLocation = self.position.rawValue + drag.translation.height
        let positionAbove: CardPosition
        let positionBelow: CardPosition
        let closestPosition: CardPosition

        if cardTopEdgeLocation <= CardPosition.middle.rawValue {
            positionAbove = .top
            positionBelow = .middle
        } else {
            positionAbove = .middle
            positionBelow = .bottom
        }

        if (cardTopEdgeLocation - positionAbove.rawValue) < (positionBelow.rawValue - cardTopEdgeLocation) {
            closestPosition = positionAbove
        } else {
            closestPosition = positionBelow
        }

        if verticalDirection > 0 {
            self.position = positionBelow
        } else if verticalDirection < 0 {
            self.position = positionAbove
        } else {
            self.position = closestPosition
        }
    }
}

enum CardPosition: CGFloat {
    case top = 100
    case middle = 500
    case bottom = 850
}

enum DragState {
    case inactive
    case dragging(translation: CGSize)

    var translation: CGSize {
        switch self {
        case .inactive:
            return .zero
        case .dragging(let translation):
            return translation
        }
    }

    var isDragging: Bool {
        switch self {
        case .inactive:
            return false
        case .dragging:
            return true
        }
    }
}
...