I want to get the position when the user taps on a button to display another view at the button's position. The button is placed inside a ScrollView
, so its position can change. I'm using GeometryReader
to read the position. However, GeometryReader
fills all the space of the parent view, so we need to limit its width using the .frame
modifier. This approach works, but since my app is localized, the text of the button label has different widths in different languages. Therefore, I want a better method to automatically adjust the button's width instead of setting it to a fixed value.
Here is my current code:
GeometryReader { geometry in
Button(action: {
optionPosition = geometry.frame(in: .global)
isFilterShown = true
}) {
Image(systemName: "slider.horizontal.3")
.font(.system(size: 18, weight: .light))
.foregroundColor(Color(.label))
Text("_filter_")
.font(.regular(size: 16))
.foregroundColor(Color(.label))
}
.padding(8)
.background(RoundedRectangle(cornerRadius: 8).fill(Color(.secondarySystemBackground)))
}
Does anyone have a better solution for this case?
I found a solution; however, I still feel it is inefficient because we need to update the position on scroll and maintain a separate variable to store it.
Button(action: {
isFilterShown = true
}) {
Image(systemName: "slider.horizontal.3")
.font(.system(size: 18, weight: .light))
.foregroundColor(Color(.label))
Text("_filter_")
.font(.regular(size: 16))
.foregroundColor(Color(.label))
}
.padding(8)
.background(
GeometryReader { geometry in
RoundedRectangle(cornerRadius: 8).fill(Color(.secondarySystemBackground))
.onAppear {
filterPosition = geometry.frame(in: .global)
}
.onChange(of: geometry.frame(in: .global)) {
filterPosition = $0
}
}
)