How to Correctly Do Up an Adjustable Split View in Swiftui

How to correctly do up an adjustable split view in SwiftUI?

From what I have observed, the issue seems to be coming from the handle being repositioned while being dragged along. To counteract that I have set an inverse offset on the handle, so it stays in place. I have tried to cover up the persistent handle position as best as I can, by hiding it beneath the other views (zIndex).

I hope somebody else got a better solution to this question. For now, this is all that I have got:

import PlaygroundSupport
import SwiftUI

struct SplitView<PrimaryView: View, SecondaryView: View>: View {

// MARK: Props

@GestureState private var offset: CGFloat = 0
@State private var storedOffset: CGFloat = 0

let primaryView: PrimaryView
let secondaryView: SecondaryView

// MARK: Initilization

init(
@ViewBuilder top: @escaping () -> PrimaryView,
@ViewBuilder bottom: @escaping () -> SecondaryView)
{
self.primaryView = top()
self.secondaryView = bottom()
}

// MARK: Body

var body: some View {
GeometryReader { proxy in
VStack(spacing: 0) {
self.primaryView
.frame(height: (proxy.size.height / 2) + self.totalOffset)
.zIndex(1)

self.handle
.gesture(
DragGesture()
.updating(self.$offset, body: { value, state, _ in
state = value.translation.height
})
.onEnded { value in
self.storedOffset += value.translation.height
}
)
.offset(y: -self.offset)
.zIndex(0)

self.secondaryView.zIndex(1)
}
}
}

// MARK: Computed Props

var handle: some View {
RoundedRectangle(cornerRadius: 5)
.frame(width: 40, height: 3)
.foregroundColor(Color.gray)
.padding(2)
}

var totalOffset: CGFloat {
storedOffset + offset
}
}

// MARK: - Playground

let splitView = SplitView(top: {
Rectangle().foregroundColor(.red)
}, bottom: {
Rectangle().foregroundColor(.green)
})

PlaygroundPage.current.setLiveView(splitView)

Just paste the code inside XCode Playground / Swift Playgrounds

If you found a way to improve my code please let me know.

Increase/Decrease the size of a view horizontally by dragging the edges of it

import SwiftUI

struct ContentView: View {
let minWidth: CGFloat = 100
@State var width: CGFloat?

var body: some View {
HStack(alignment: .center) {
Spacer()
RedRectangle(width: width ?? minWidth)
Resizer()
.gesture(
DragGesture()
.onChanged { value in
width = max(minWidth, width! + value.translation.width)
}
)
Spacer()
}
.onAppear {
width = minWidth
}
}
}

struct RedRectangle: View {
let width: CGFloat

var body: some View {
Rectangle()
.fill(Color.red)
.frame(width: width, height: 100)
}
}

struct Resizer: View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(width: 8, height: 75)
.cornerRadius(10)
}
}

How to change the height of the object by using DragGesture in SwiftUI?

The correct calculation is

.gesture(
DragGesture()
.onChanged { value in
height = max(MIN_HEIGHT, height + value.translation.height)
}
)

Also, remove the infinite width. It's invalid.

.frame(minHeight: 0, maxHeight: height)

or

.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: height)


Related Topics



Leave a reply



Submit