How to force navigation bar to show background in SwiftUI? - ios

I have the following (on iOS 16):
NavigationStack
{
Form
{
....
}
}
.navigationTitle("Hello")
.navigationBarTitleDisplayMode(.inline)
The navigation bar background only appears when scrolling the Form upwards.
How can I make sure that the background is always showing?

use this to always show the background:
.toolbarBackground(.visible, for: .navigationBar)
and this to style it:
.toolbarBackground(.red, for: .navigationBar)

Related

How to set TabBarIcon color correctly in SwiftUI since .accentColor is deprecated?

It seems quite hard to change the color of the selected UITabBarItem in SwiftUI. To define the design at central place in the app, I tried to use .appearance() to do this, but nothing worked:
// Only effects the unselected items
UITabBar.appearance().unselectedItemTintColor = .red
// No effect, deprecated in iOS 8(!)
UITabBar.appearance().selectedImageTintColor = .cyan
// Only effects the title, not the icon
UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor: UIColor.green], for: .normal)
// No effect
UITabBar.appearance().tintColor = .red
The only thing that works is to not use the appearance proxy but setting the color "manually" in the SwiftUI View definition using .accentColor
struct MainView: View {
var body: some View {
TabView {
SomeView()
.tabItem {
Label("Main", systemImage: "list.dash")
.tint(.green) // No effect
}
.tint(.yellow) // No effect
}
.accentColor(.orange)
// No effect
//.tint(.red)
}
}
However, .accentColor will also be deprecated:
'accentColor' will be deprecated in a future version of iOS: Use the
assets catalog's accent color or View.tint(_:) instead
Using .tint on the TabView has no effect. UITabBarItem has no tint appearance property.
To how to correctly set the icon color without using accentColor (preferably via the appearance)

Swaping the color scheme of tab view indicators in SwiftUI 3

I have a tab view defined by this code:
TabView {
ViewOne()
ViewTwo()
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
This creates a tabview indicator like this. However id like to either use a darker color or swap the scheme of this one component.
I believe the indexViewStyle is not customizable at the moment, because the IndexViewStyle protocol is not public.
However, you can try to use TabView(selection:) init and overlay, or somehow hide the original indexView and just make your own.
Not sure what does you mean by color scheme. If you want to change the color of the indicator or remove the background of the color you can do this:
struct PageView: View {
init() {
UIPageControl.appearance().currentPageIndicatorTintColor = .cyan
UIPageControl.appearance().pageIndicatorTintColor = UIColor.red.withAlphaComponent(1)
UIPageControl.appearance().backgroundStyle = .minimal
}
var body: some View {
TabView {
Text("First")
Text("Second")
Text("Third")
}
.tabViewStyle(.page)
}
}
UIPageControl.appearance().currentPageIndicatorTintColor change the color of the current page dot. UIPageControl.appearance().pageIndicatorTintColor change the rest of the dot. Also, in Swift 14 onwards, new style is introduced to UIPageControl. The prominent style which is the one you have now with the rounded view and the old style called minimal style which I change in my code above in UIPageControl.appearance().backgroundStyle.
The output of my code is
If you want to change the color accordingly to dark or light mode, you can add a color set in your Assets and use it.

How to change navigation bar tint color for pushed view in SwiftUI?

[1 SOLUTION FOUND!]
Thanks to George's comment I was able to find a solution https://stackoverflow.com/a/70353393/882987 but if somebody has any other solution feel free to write it :)
I am having some issues with setting custom navigation bar tint color in SwiftUI for "pushed" views.
Code is something like this, having a stack of items and tapping on each of them we show/push some detail view:
NavigationView {
ScrollView {
LazyVStack(alignment: .leading) {
ForEach(items) { item in
NavigationLink(destination: DetailItemView(item))) {
ListItemView(item)
}
}
}
}
}
And I would like to have different navigation bar tint color for each view that gets pushed.
Is there a way to achieve that?
Thanks to George's comments I was able to find a solution, using basic Binding.
In the view A I added:
#State private var navColor = Color.primary
and I added the modifier:
NavigationView {
...
}
.accentColor(navColor)
And in view B I added:
#Binding var navColor: Color
So I can change the navColor property to anything I want in view B and it will update the accentColor (and with that the navigation bar tint color)

SwiftUI - After Moving App to Background Then Restoring to Foreground, TabView Loses Color

I have a SwiftUI 5.3 Multiplatform app in Xcode 12.2 on MacOS 11.01 running on iOS 14.2 that uses a custom color asset for light/dark modes. When starting up the app, it functions perfectly fine alternating between light and dark modes. All the colors change accordingly.
However, when in dark mode, if I move the app to the background and bring another app to the foreground, then go back to my app (restoring from being in the background), the TabView color washes out completely. The NavigationView at the top functions normally, as expected at all times. If I then switch to light mode, the correct light mode color appears for the TabView. Switching back to dark mode restores the correct dark mode TabView colors. If I again move the app to the background, look at another app, then bring my app back to the foreground, the TabView color is again washed out.
I haver tried countless things with color calls using init and .onAppear, but nothing has corrected this behavior.
Any thoughts? Thanks for taking the time to help me sort this out.
Edited for added clarity. Code is added here:
import SwiftUI
struct TabbedView: View {
init() {
UINavigationBar.appearance().titleTextAttributes = [NSMutableAttributedString.Key.foregroundColor:UIColor(named: "mainTextColor") as Any]
UINavigationBar.appearance().barTintColor = UIColor(named: "barBackground")
UINavigationBar.appearance().tintColor = UIColor(named: "mainTextColor")
UITabBar.appearance().isOpaque = true
UITabBar.appearance().unselectedItemTintColor = UIColor(named: "unselectedTabColor")
UITabBar.appearance().barTintColor = UIColor(named: "barBackground")
}
var body: some View {
TabView {
ContentView()
.tabItem {
VStack {
Image("Topics69x69")
Text("Topics")
}
}.tag(0)
ChangesView()
.tabItem {
VStack {
Image("Changes69x69")
Text("Changes")
}
}.tag(1)
GospelView()
.tabItem {
VStack {
Image("Gospel69x69")
Text("Gospel")
}
}.tag(2)
CopyrightView()
.tabItem {
VStack {
Image("Copyright75x75")
Text("Copyright")
}
}.tag(3)
AboutView()
.tabItem {
VStack {
Image("About75x75")
Text("About")
}
}.tag(4)
} // TabView
// Sets color of the selected tab on the TabBar
.accentColor(Color("tabImageTintColor"))
} // View
} // Main View

UITabBar transparent labels bug in iOS 13

iOS: 13.1.2
Xcode: 11.1 (11A1027)
In our tab bar we opted for using transparent text for the tab items, so in iPhone we only show the tab item image, while the text is invisible (and it should be only visible on iPad), we do this by calling:
extension UITabBarItem {
func updateTitleVisibility(for traitCollection: UITraitCollection) {
switch traitCollection.horizontalSizeClass {
case .compact:
hideTabBarTitle()
default:
showTabBarTitle()
}
}
func hideTabBarTitle() {
imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)
setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .selected)
}
func showTabBarTitle() {
imageInsets = .zero
setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.licorice], for: .normal)
setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.secondaryBlue], for: .selected)
}
}
When compiling our app for iOS 13 (it didn’t happen on iOS 12), there is a strange behavior happening (notice the tab bar):
Video of the bug # Imgur
(^ i didn't manage to embed it in the post)
So the tab text sudden shows for the inactive tabs after presenting a full screen view controller, but incredibly enough when checking the view debugger the labels that are supposed to be transparent are indeed transparent
Has anybody seen a behavior like that? How can I fix it
Well, this is due to the behavior in the default dark mode on iOS 13.
To achieve what you wanted with labels as on iOS versions below 13,
Simply add this into your Info.plist:
<key>UIUserInterfaceStyle</key>
<string>Light</string>
What this essentially does is changing the global user interface style to the light style which is the default style on iOS versions below 13.
If you won't prefer to change the user interface style, you can also change the tint color of the unselected items on the tab bar:
tabBar.unselectedItemTintColor = .darkGray
or to any other tint color of your choice.

Resources