How to hide the home indicator with SwiftUI?
iOS 16
you can use the .persistentSystemOverlays
and pass in .hidden
to hide all non-transient system views that are automatically placed over our UI
Text("Goodbye home indicator, the multitask indicator on iPad, and more.")
.persistentSystemOverlays(.hidden)
How to dynamically hide the status bar and the home indicator in SwiftUI?
I was able to solve the problem with the SwiftUI view not extending beyond the safe area insets for the status bar and the home indicator by completely switching to a storyboard based project template and embedding my views through a custom UIHostingController as described in this solution by Casper Zandbergen.
Before I was re-integrating the hosting controller into the SwiftUI view hierarchy by wrapping it with a UIViewRepresentable instance, which must have caused the complications in handling the safe area.
By managing the whole app through the custom UIHostingController subclass it was even easier to get the hiding of the home indicator working. As much as I love SwiftUI I had to realize that, with its current limitations, UIKit was the better option here.
Final code (optimized version of the solution linked above):
ViewController.swift
import SwiftUI
import UIKit
struct HideUIPreferenceKey: PreferenceKey {
static var defaultValue: Bool = false
static func reduce(value: inout Bool, nextValue: () -> Bool) {
value = nextValue() || value
}
}
extension View {
func userInterfaceHidden(_ value: Bool) -> some View {
preference(key: HideUIPreferenceKey.self, value: value)
}
}
class ViewController: UIHostingController<AnyView> {
init() {
weak var vc: ViewController? = nil
super.init(
rootView: AnyView(
ContentView()
.onPreferenceChange(HideUIPreferenceKey.self) {
vc?.userInterfaceHidden = $0
}
)
)
vc = self
}
@objc required dynamic init?(coder: NSCoder) {
weak var vc: ViewController? = nil
super.init(
coder: coder,
rootView: AnyView(
ContentView()
.onPreferenceChange(HideUIPreferenceKey.self) {
vc?.userInterfaceHidden = $0
}
)
)
vc = self
}
private var userInterfaceHidden = false {
didSet { setNeedsUpdateOfHomeIndicatorAutoHidden() }
}
override var prefersStatusBarHidden: Bool {
userInterfaceHidden
}
override var prefersHomeIndicatorAutoHidden: Bool {
userInterfaceHidden
}
}
Strange home bar appearance in SwiftUI app
That is not an issue, it should be like that, since we have no touch id in new iPhone models, that things play as kind of help in Screen. And when you use edgesIgnoringSafeArea
in your code, you get access to under area and back area of that shape for Color works!
That shape is used for Swipe up to go iPhone main screens.
Look at the iPhone 8, it has touch, and look at iPhone 11, No touch ID!
Move Index View above home indicator in Tab View
EDIT: See also @nekno's fantastic additions!
This is possible if you create a custom UIPageControl
, manually tag each tab in the TabView
, and make sure to keep track of the numberOfPages
:
struct PageControlView: UIViewRepresentable {
@Binding var currentPage: Int
@Binding var numberOfPages: Int
func makeUIView(context: Context) -> UIPageControl {
let uiView = UIPageControl()
uiView.backgroundStyle = .prominent
uiView.currentPage = currentPage
uiView.numberOfPages = numberOfPages
return uiView
}
func updateUIView(_ uiView: UIPageControl, context: Context) {
uiView.currentPage = currentPage
uiView.numberOfPages = numberOfPages
}
}
struct ContentView: View {
@State var isSheetUp = false
var body: some View {
Button("Present") {
isSheetUp.toggle()
}
.sheet(isPresented: $isSheetUp) {
Sheet()
}
}
struct Sheet: View {
@State var currentPage = 0
@State var numberOfPages = 3
var body: some View {
NavigationView {
ZStack {
TabView(selection: $currentPage) {
Page().tag(0)
Page().tag(1)
Page().tag(2)
}
// Comment this to switch layout issue
.ignoresSafeArea(edges: .bottom)
.tabViewStyle(.page(indexDisplayMode: .never))
.indexViewStyle(.page(backgroundDisplayMode: .always))
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.inline)
VStack {
Spacer()
PageControlView(currentPage: $currentPage, numberOfPages: $numberOfPages)
}
}
}
}
}
struct Page: View {
var body: some View {
ScrollView {
VStack {
Rectangle()
.foregroundColor(.teal)
.padding()
.frame(minHeight: 10000)
}
}.background(Color.brown)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Related Topics
How to Draw on an Image in Swift
Check If My iOS Application Is Updated
How to Set the Rootviewcontroller with Swift, iOS 7
Phonegap on iOS with Absolute Path Urls for Assets
Get Version Number of iOS Universal Framework in Client
How to Get 18-Digit Current Timestamp in Swift
What Is the Swift Preprocessor Equivalent to iOS Version Check Comparison
Shrink Large Title When Scrolling (Not Uitableviewcontroller) iOS 11
Custom Font on Uibutton Title Clipped on Top of Word
Adding Swift Files to Test Target Not Fixing Unit Tests
How Long Does a Push Notification Sit in Queue Before Being Removed
Error Domain=Nsposixerrordomain Code=100 "Protocol Error"
Uibarbuttonitem Custom View in Uinavigationbar
Does iPhone Support Hardware-Accelerated Aes Encryption
Core Data Predicate:Unimplemented SQL Generation for Predicate