stevengharris/SplitView

Setting fraction programmatically (after the split view is shown already)

Closed this issue · 2 comments

I couldn't figure out a way how to set the split fraction between primary and secondary view programmatically (e.g. by manipulating the FractionHolder). To me it looks like the fraction holder gets updated after the drag is over, but any changes to the value of the fraction holder are not propagated into the view. I'd like to provide a button that resets the split fraction to 0.5. Am I right in assuming that this is currently not possible?

I was surprised to find that this is currently not possible. For one thing, I didn't publish the value of FractionHolder. Ugh. Doing that seems harmless:

public class FractionHolder: ObservableObject {
    @Published public var value: CGFloat {
        didSet {
            setter?(value)
        }
    }

If you do that, then you can monitor changes in Split on the ZStack:

    .onChange(of: fraction.value) { new in constrainedFraction = new }  // <- new line 102

This will trigger when fraction is set at the end of drag, but that won't matter, since new will be the constrainedFraction at the end of drag. Now if you change the state of the FractionHolder, the Split view will update. I will probably double-check all this later and incorporate the changes, but this should do the trick for now. The added onChange here in Split only will work for HSplit and VSplit, too (i.e., they don't need to be modified). Here's what I used to test:

struct FractionTestView: View {
    @State private var fraction = FractionHolder(0.25)
    var body: some View {
        VStack {
            Button(action: { fraction.value = 0.5 }, label: { Text("Restore to middle") })
            HSplit(left: {Color.red}, right: {Color.green})
                .fraction(fraction)
        }
    }
}

Thanks for your response and for identifying a solution! In your new line 102, you might also have to check for the fraction constraints to make sure that internal invariants aren't broken by a fraction provided from outside that is not valid.