4

DynamicScalingView is a child view with two buttons designed to have equal width & height using preferencekey

Issue: When DynamicScalingView is embedded in NavigationView it not longer adapts to intrinsic and increases its frame size. Current implementation without Navigation works fine but would like to understand how to fix this issue when embedded in NavigationView

  • Uncomment NavigationView in sample view to reproduce the issue
  • DynamicScalingView should adapt to Dynamic font size and increase its frame size maintaining equal width & height constraint between the buttons.

XCode 12.2 and iOS 14.2

struct SampleView: View {
    var body: some View {
        GeometryReader { gr in
            //NavigationView {
                ScrollView {
                    VStack {
                        // fills whatever space is left
                        Spacer()
                            .foregroundColor(.clear)

                        // view should fit with intrinsic content size
                        DynamicScalingView()
                            .padding(.horizontal, 20)
                            .border(Color.blue, width: 1)
                    }
                    .padding(.bottom, 20)
                    .border(Color.red, width: 1)
                    .frame(minHeight: gr.size.height)
                    .navigationBarHidden(true)
                }
        //  }
        }
    }

    struct DynamicScalingView: View {
        @State private var labelHeight = CGFloat.zero

        var body: some View {
            HStack {
                Button(action: {}, label: {
                    Text("Some Text Some Text Some Text")
                        .padding(.horizontal, 2)
                })
                    .foregroundColor(Color.white)
                    .padding(.vertical)
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .frame(minHeight: labelHeight)
                    .background(Color.blue)
                    .cornerRadius(8)
                    .fixedSize(horizontal: false, vertical: true)
                    .background(GeometryReader {
                        Color.clear
                            .preference(
                                key: ViewHeightKey.self,
                                value: $0.frame(in: .local).size.height
                            )
                    })

                Button(action: {}, label: {
                    Text("Some Text")
                        .padding(.horizontal, 2)
                })
                    .foregroundColor(Color.white)
                    .padding(.vertical)
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .frame(minHeight: labelHeight)
                    .background(Color.blue)
                    .cornerRadius(8)
                    .fixedSize(horizontal: false, vertical: true)
                    .background(GeometryReader {
                        Color.clear
                            .preference(
                                key: ViewHeightKey.self,
                                value: $0.frame(in: .local).size.height
                            )
                    })
            }
            .onPreferenceChange(ViewHeightKey.self) {
                self.labelHeight = $0
            }
        }
    }

    struct ViewHeightKey: PreferenceKey {
        static var defaultValue: CGFloat { 0 }
        static func reduce(value: inout Value, nextValue: () -> Value) {
            value = max(value, nextValue())
        }
    }
}
Pablo Dev
  • 317
  • 5
  • 16

0 Answers0