1

I'm using this solution from this post for my custom pager tabview and I want to give each tab padding of 16. This is the code:

struct PagerView<Content: View>: View {
let pageCount: Int
@Binding var canDrag: Bool
@Binding var currentIndex: Int
let content: Content


init(pageCount: Int, canDrag: Binding<Bool>, currentIndex: Binding<Int>, @ViewBuilder content: () -> Content) {
    ...
}


@GestureState private var translation: CGFloat = 0

var body: some View {
    GeometryReader { geometry in
        HStack(spacing: 16) {
            self.content.frame(width: geometry.size.width)
            //                    .padding(16)
        }
        .padding(16)
        .frame(width: geometry.size.width, alignment: .leading)
        .offset(x: -CGFloat(self.currentIndex) * (geometry.size.width - 16))
        .offset(x: self.translation)
        .animation(.interactiveSpring(), value: currentIndex)
        .animation(.interactiveSpring(), value: translation)
        .gesture(!canDrag ? nil : // <- here
            
            DragGesture()
                .updating(self.$translation) { value, state, _ in
                    
                    state = value.translation.width
                }
                .onEnded { value in
                    let offset = value.translation.width / geometry.size.width
                    let newIndex = (CGFloat(self.currentIndex) - offset).rounded()
                    self.currentIndex = min(max(Int(newIndex), 0), self.pageCount - 1)
                }
        )
    }
}

}

However, no matter how much I've tried, I can not give it the right padding. Please check the image. enter image description here

I've tried to give content padding, Hstack spacing, or frame but none of them work.

Any suggestion would be appreciated

Duc Dang
  • 186
  • 1
  • 14

2 Answers2

0

This is a case where order of modifiers is important. You were very close with your instinct to add the padding onto the content, but you failed to consider the modifier that was already there. While it makes the code look longer, in these cases I always keep my modifiers on separate lines to help make it apparent what you are adding a modifier to:

GeometryReader { geometry in
    HStack(spacing: 16) {
        self.content
            .padding(16) // put the padding her so it modifies the content, not the frame
            .frame(width: geometry.size.width)
    }
    ...
}

By trying to place the padding AFTER the frame, you were adding 16 to the whole width which was causing the views to be offset. What you wanted to do was add padding to the content to add it by 16, and then constrain both the view and the padding to be the exact width of the view. The math does not work out if you add to the frame.

Yrb
  • 8,103
  • 2
  • 14
  • 44
0

Thanks, Yrb for the hint. Since the whole custom tab view is based on Hstack, it is really hard to give each element padding horizontally. Instead, I calculated the x offset based on the current Index:

            HStack(spacing: 16) { // <-- here
            self.content
                .frame(width: geometry.size.width)

        }
        .offset(x: -CGFloat(self.currentIndex) * (geometry.size.width) - CGFloat((currentIndex * 16))) <-- here
Duc Dang
  • 186
  • 1
  • 14