On my app I have a floating button. Because I don’t want that this button to obstruct contents, I placed it on .safeAreaInset(egde: bottom) { }
. ScrollView handles this safe area, and allow user to scroll extra distance.
However there is a problem I could not fix. The content on the safe area is not clickable.
On the example below, even though the buttons are visible on the bottom of the screen, they cannot be clicked because they are on the safe area.
Is there any fix or alternatives to achive the behaviour I want?
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView {
VStack {
ForEach(Array(1...100), id: .description) { i in
HStack {
Button(
action: {
print("(i) clicked")
},
label: {
Text("Button (i)")
}
)
Spacer()
Text("Description (i)")
}
.frame(maxWidth: .infinity)
}
}
.padding()
}
.safeAreaInset(edge: .bottom, alignment: .trailing) {
Color.red.frame(width: 75, height: 75)
.clipShape(Circle())
.padding()
}
}
}
#Preview {
ContentView()
}
4
The safe area cannot be any shape you want – it must be rectangular.
An alternative way to achieve this is by putting padding
on the VStack
, and put the red circle in a simple overlay
.
ScrollView {
VStack {
ForEach(Array(1...100), id: .description) { i in
HStack {
Button(
action: {
print("(i) clicked")
},
label: {
Text("Button (i)")
}
)
Spacer()
Text("Description (i)")
}
.frame(maxWidth: .infinity)
}
}
.padding()
.padding(.bottom, 75) // <--- here
}
.contentMargins(.bottom, 75, for: .scrollIndicators)
.overlay(alignment: .bottomTrailing) {
Color.red.frame(width: 75, height: 75)
.clipShape(Circle())
.padding(.trailing)
}
Note that I also added .contentMargins(.bottom, 75, for: .scrollIndicators)
to make the scroll indicator stop just above the red circle, recreating the same effect that safeAreaInset
would have created.