I want to use the new iOS 16 Buttom Sheet Feature to create a view like the find my:
Unfortunately the TabView gets hidden behind the Sheet:
My Code:
TabView {
Text("View 1")
.sheet(isPresented: .constant(true)) {
Text("Sheet View Content")
.presentationDetents([.medium, .large])
}
.tabItem {
Label("Menu", systemImage: "list.dash")
}
Text("View 2")
.tabItem {
Label("Order", systemImage: "square.and.pencil")
}
}
How can I achieve this?
No Solution for the moment
Unfortunately, it is not currently possible to show a modal sheet with a tab bar visible using the current version of SwiftUI. This issue has been raised by other developers on the Apple developer forums and on other threads on StackOverflow, such as the following:
https://developer.apple.com/forums/thread/711702
Swift UI show modal sheet with tab bar visible
SwiftUI present sheet in a TabItem of TabView using presentationDetents
I am also searching for a solution to this problem.
I am currently working on a custom ViewModifier to address this issue, and if it is successful, I will make it publicly available on GitHub.
Related
I have a SwiftUI app which uses a custom navigation bar. Because of that, I need to handle the back navigation separately (both the back button and the swipe gesture). Everything went fine up until now, when I need to use a TabView to swipe between pages. The code below illustrates what I'm trying to achieve:
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Go to second view")
}
}
}
}
SecondView.swift
import SwiftUI
// Being able to go back by swiping
// https://stackoverflow.com/questions/59921239/hide-navigation-bar-without-losing-swipe-back-gesture-in-swiftui
extension UINavigationController: UIGestureRecognizerDelegate {
override open func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
struct SecondView: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack(alignment: .leading) {
Image(systemName: "chevron.left")
.foregroundColor(Color(.systemBlue))
.font(.title2)
.onTapGesture {
self.presentationMode.wrappedValue.dismiss()
}
.padding()
TabView {
Text("Test 1")
.tag(1)
Text("Test 2")
.tag(1)
Text("Test 3")
.tag(3)
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
.background(Color(.systemGray6))
.navigationBarHidden(true)
}
}
Note that I didn't add the custom navigation bar for the second view, I've just hidden the default navigation bar, as the custom bar is not needed to solve this problem.
When the user is inside the SecondView and presses the back button, everything works as expected. The problem appears when he tries to swipe back, as the swipe back gesture is captured by the TabView. I want to keep the 'swipe-between-pages' functionality of the TabView while being able to go back to ContentView when the user swipes right from the leftmost part of the screen.
This problem only appears when using TabViews, other types of content handle the swipe back gesture without problems.
To solve this problem, I could add a horizontal padding to the TabView like this:
TabView {
// content
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.padding(.horizontal)
and then the user would have some space to swipe back, but this solution is not so good when some views inside the TabView need to take the whole width of the screen.
Is there any way to handle the swipe back gesture in this particular case? Maybe another possible solution would be customizing the TabView to ignore the drag gesture when the first view is presented and a swipe right gesture is captured (I don't know how to implement that).
I ran into this same problem. I solved it by wrapping my first tabview in with a geometryReader. When the bounds of that view is more than a quarter off the screen, I dismiss the view.
When I go to my second page which has a ScrollView, and I scroll to the point it becomes inline and then return to the mainView - the navigationBarTitles is being overwritten with both navigationBarTitles.
I am using Xcode Version 12.5 (12E262) and this is iOS 14.
It is happening both in the simulator and on a device.
MainView
ScrollView
ScrollView scrolled so it becomes inline
And when I return to the MainView from the inline NavBar I get this.
It is fine - unless I have scrolled. And what makes it even more confusing it only does it about 25% of the time.
I am just using "self.presentationMode.wrappedValue.dismiss()" to return to the mainView
I am using a NavigationLink to go to the second page.
NavigationLink(destination: ScrollView(), isActive: $showScroll ) { EmptyView() }
Is there something I have missed when dismissing from Scrolling?
very plain code for the scrollView.
I am obviously missing something or this is a big issue with SwiftUI and Xcode.
Thank you.
var body: some View {
ScrollView(showsIndicators: false) {
}
.navigationBarBackButtonHidden(true)
.navigationBarTitle("scrollView Page")
.navigationBarItems(
leading:
Button(action:{
self.presentationMode.wrappedValue.dismiss()},
label: {
Image(systemName: "arrow.left")
})
}
I'm trying to create a TabView Slider in SwiftUI with 3 modals that will onboard a user. The default PageTabViewStyle() is a little basic and I'm wanting it to animate with the default slide speed etc.
I've tried appending animation along with the transition from what I've seen online including StackOverflow but it doesn't work.
Here's what I currently have:
ZStack {
Color.black
TabView(selection: $currentTab) {
ForEach(OnboardingData.list) { viewData in
OnboardingModal(data: viewData)
.tag(viewData.id)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.animation(.easeInOut)
.transition(.slide)
}
I have set up a TabView in my application, so that I can swipe horizontally between multiple pages, but I also have an unwanted vertical scroll that may appear, with a bounce effect so. How can I disable this vertical scroll?
My code:
struct ContentView: View {
#State private var currentTabIndex: Double = 0
var body: some View {
VStack {
TabView(selection: $currentTabIndex) {
Text("Text n°1")
.tag(0)
Text("Text n°2")
.tag(1)
}
.border(Color.black)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
}
}
I had this same problem. It's not an exact solution, but you can turn off bouncing on scrollviews (which is used within a TabView). And as long as the items within the TabView are not larger than the TabView frame, it should act as if you disabled vertical scrolling.
I would call it either .onAppear or in your init function:
.onAppear(perform: {
UIScrollView.appearance().bounces = false
})
Note: this disables the bouncing on ALL scrollviews across your app... So you may want to re-enable it .onDisappear.
Still an issue with Xcode 12.4.
I managed to workaround that by wrapping the TabView within a ScrollView and using the alwaysBounceVertical property set to false, as follow:
ScrollView(.horizontal) {
TabView {
///your content goes here
}
.tabViewStyle(PageTabViewStyle())
}
.onAppear(perform: {
UIScrollView.appearance().alwaysBounceVertical = false
})
.onDisappear(perform: {
UIScrollView.appearance().alwaysBounceVertical = true
})
I actually came across this because I saw this effect in a tutorial but couldn’t replicate it on iOS 15.2. However, I managed to replicate it on iOS 14.4 on another simulator side by side. So I guess this behaviour is disabled or fundamentally changed in the newer iOS.
Demonstration
Here I have use SwiftUI 2.0 and manage TabBar badge count. Reference of
https://medium.com/flawless-app-stories/swiftui-tutorial-showing-badge-on-tab-bar-item-d71e4075b67a
In Xcode 12.1 , the badge gets pushed up when the keyboard appears
How to mange this badge count When keyboard appear ?
Try adding .ignoresSafeArea(.keyboard) to your GeometryReader and/or the badge’s containing ZStack.
Your view is resizing to avoid the keyboard, which is the new default in iOS 14. Use the new .ignoresSafeArea(.keyboard) modifier to disable that behavior.
As of SwiftUI 3, you can use the .badge modifier to add a badge to your tab item. This requires iOS 15 or later.
Examples:
struct Tabs_Previews: PreviewProvider {
static var previews: some View {
TabView {
Text("String tab")
.tabItem {
Text("String")
Image(systemName: "text.quote")
}
.badge("hi")
.tag("string")
Text("Int tab")
.tabItem {
Text("Int")
Image(systemName: "number.circle")
}
.badge(123)
.tag("string")
}
}
}
Result:
You can use an Int, a String, a Substring, a LocalizedStringKey, or a Text. In my testing, the badge ignores any styling applied to the Text.