Adding a Subtitle under NavigationTitle - swiftui

Let's say I have the following code:
struct SwiftUIView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello")
Text("World")
}
.navigationTitle("SwiftUI")
}
}
}
I'd like to add a smaller subtitle right under SwiftUI. I tried adding something like .navigationSubtitle("") but it doesn't exist. I also tried reading the documentation, and it does mention func navigationSubtitle(_ subtitle: Text) -> some View, but I'm just not sure how to add that to my code. Thanks in advance!

You can add a ToolbarItem with the principal placement:
struct SwiftUIView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello")
Text("World")
}
// .navigationTitle("SwiftUI") this won't make any changes now
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("title")
Text("subtitle")
}
}
}
}
}
}
The downside is that it overrides the navigation title, so any changes made with navigationTitle won't visible.

You can do something like:
.navigationBarItems(leading:
VStack(alignment: .leading, spacing: 5) {
Text("SwiftUI")
.font(.system(size: 35, weight: .semibold, design: .default))
Text("Subtitle")
}
)

Using a VStack in a toolbar causes the child view to display < Back for the the back navigation button rather than the title of the parent view. What I ended up doing is:
.navigationTitle("Title") // Will not be shown, but will be used for the back button of the child view
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("Real Title").font(.headline)
Text("Subtitle").font(.subheadline)
}
}
}

I ended up doing something different: instead of making "SwiftUI" a navigation title, I just put it inside a VStack with the rest of the body, like so:
struct SwiftUIView: View {
var body: some View {
NavigationView {
VStack {
//Header
VStack(alignment: .leading, spacing: 5) {
Text("SwiftUI")
.font(.system(size: 35, weight: .semibold, design: .default))
Text("Subtitle")
}
.padding()
.padding(.leading, -110) //I'm still not sure how to give it a leading alignment without hardcoding it
Divider()
Spacer()
//Body
VStack {
Text("Hello")
Text("World")
}
Spacer()
//Navbar title
}
}
}}
Thank you all for the help regardless!

Related

Prevent SwiftUI Divider expanding horizontally

I have the following setup:
struct ContentView: View {
var body: some View {
VStack {
Text("Title").font(.title)
HStack {
Text("Hello:").bold()
Text("World")
}
}
.padding()
.background {
RoundedRectangle(cornerRadius: 8).stroke(.black)
}
}
}
which renders as follows:
When I add a Divider() into the VStack…
struct ContentView: View {
var body: some View {
VStack {
Text("Title").font(.title)
Divider() // Added this
HStack {
Text("Hello:").bold()
Text("World")
}
}
.padding()
.background {
RoundedRectangle(cornerRadius: 8).stroke(.black)
}
.padding()
}
}
… it forces the VStack to expand horizontally as large as possible.
How do I make the Divider fit to the other VStack content?
Having written the question, I tried some more things, and found a solution. Leaving here in case it is useful for others.
I just needed to add
.fixedSize(horizontal: true, vertical: false)
to the VStack, which makes all the subviews have the same horizontal size, resulting in…

NavigationLink in Detail Page

hey folk I have a problem I wanna make a NavationLink in Detail Page to show other Fruits. but when I click it it will make a page(with NavigationView) inside a Parent’s Page actually I want to replace it, not push a new one. this is my code
var body: some View {
NavigationView {
ScrollView(showsIndicators:false) {
VStack(alignment: .center, spacing: 20) {
// HEADER
FruitHeaderView(Fruit: fruit)
VStack(alignment:.leading,spacing:20) {
// TITLE
Text("\(fruit.title)")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(fruit.gradientColors[1])
// HEADLINE
Text("\(fruit.headline)")
.font(.headline)
.fontWeight(.bold)
// SUBHEADING
Text("Learn more about \(fruit.title)".uppercased())
.fontWeight(.bold)
.foregroundColor(fruit.gradientColors[1])
// DESCRIPTION
Text("\(fruit.description)")
.multilineTextAlignment(.leading)
} //: VSTACK
.padding(.horizontal,20)
.frame(maxWidth:640,alignment: .center)
} //: VSTACK
VStack(alignment:.leading) {
Text("Other Fruit like \(fruit.title)")
.fontWeight(.bold)
.foregroundColor(fruit.gradientColors[1])
ScrollView(.horizontal, showsIndicators:false) {
HStack(spacing:30) {
ForEach(5...10,id:\.self) { item in
NavigationLink(destination: FruitDetailView(fruit: fruitsData[item])) {
AlternativeFruitView(Fruit: fruitsData[item])
}
}
}
}
}
.padding(.horizontal,20)
.frame(maxWidth:640,alignment: .center)
} //: SCROLL
.navigationBarTitle("\(fruit.title)",displayMode: .inline)
.navigationBarHidden(true)
.edgesIgnoringSafeArea(.top)
} //: NAVIGATION
.navigationViewStyle(StackNavigationViewStyle()) // iPad OS
}
and this is the result
current Build
My Problem
I know there will be calling my struct and making a new NavigationView I just wanna know is is there an API or function that I can fix my problem or not
thanks.

Navigation title not appearing correctly in SwiftUI

I have a VStack wrapped around a NavigationView. I made a NavigationTitle by adding the modifier to VStack. However, my title is not appearing near the top of the screen as it should.
Here is my code:
NavigationView{
VStack{
Image(club.image)
.resizable()
.scaledToFit()
.frame(height: 300)
Text(club.name)
.font(.system(size: 40, weight: .black))
HStack(alignment: .center, spacing: 20){
Label(title: {
Text(club.league)
.foregroundColor(.secondary)
}, icon: {
Image(systemName: "location.north.circle.fill")
.foregroundColor(.blue)
})
Label(title: {
Text(club.netWorth)
.foregroundColor(.secondary)
}, icon: {
Image(systemName: "dollarsign.circle.fill")
.foregroundColor(.blue)
})
}
}.navigationTitle(club.name)
}
I have tried adding the '.navigationTitle' modifier to the NavigationView as well, but that isn't working.
Here is an image as well:
Navigation title image
Does anybody have a solution to this?
As lorem ipsum has mentioned. It's as simple as removing the extra NavigationView. When using a Navigation Link it's assumed that it's within a NavigationView. So you only need to declare it once in the root view. If you wanted additional NavigationLink you'd add it without a NavigationView.
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Chelsea")
NavigationLink("Second View Link", destination: SecondView())
}
.navigationTitle("Chelsea")
}
}
}
struct SecondView: View {
var body: some View {
VStack {
Text("Second View")
}
.navigationTitle("Second View")
}
}

SwiftUI 2.0: Close button is not dismissing the view - how do I get the Close button to return to the previous view?

I have tried to use Buttons and Navigation Links from various examples when researched on this channel and on the net. The NavigationLink would be ok, except that the NavigationView is pushing everything down in my view.
I have a view that contains an image and a text like this: ( x Close) but when I use the code below, the Close button is not doing anything.
In ContentView() I have a (?) button that takes me from WalkthroughView(), then to the PageTabView, then to this view, TabDetailsView:
ContentView():
ZStack {
NavigationView {
VStack {
Text("Hello World")
.padding()
.font(.title)
.background(Color.red)
.foregroundColor(.white)
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation {
showOnBoarding = true
}
} label: {
Image(systemName: "questionmark.circle.fill")
}
}
}
}
.accentColor(.red)
.disabled(showOnBoarding)
.blur(radius: showOnBoarding ? 3.0 : 0)
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
}
}
.onAppear {
if !isWalkthroughViewShowing {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
showOnBoarding.toggle()
isWalkthroughViewShowing = true
}
}
}
}
WalkthroughView():
var body: some View {
ZStack {
GradientView()
VStack {
PageTabView(selection: $selection)
// shows Previous/Next buttons only
ButtonsView(selection: $selection)
}
}
.transition(.move(edge: .bottom))
}
PageTabView():
var body: some View {
TabView(selection: $selection) {
ForEach(tabs.indices, id: \.self) { index in
TabDetailsView(index: index)
}
}
.tabViewStyle(PageTabViewStyle())
}
below, is the TabDetailsView():
At the top of the view is this Close button, when pressed, should send me back to ContentView, but nothing is happening.
struct TabDetailsView: View {
#Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
let index: Int
then, inside the body:
VStack(alignment: .leading) {
Spacer()
VStack(alignment: .leading) {
// Button to close each walkthrough page...
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Image(systemName: "xmark.circle.fill")
Text("Close")
}
.padding(.leading)
.font(.title2)
.accentColor(.orange)
Spacer()
VStack {
Spacer()
Image(tabs[index].image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 415)
.padding(.leading, 10)
Text(tabs[index].title)
.font(.title)
.bold()
Text(tabs[index].text)
.padding()
Spacer()
}
.foregroundColor(.white)
}
}
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
}
Inserting view like above is not a presentation in standard meaning, that's why provided code does not work.
As this view is shown via showOnBoarding it should be hidden also via showOnBoarding, thus the solution is to pass binding to this state into view where it will be toggled back.
Due to deep hierarchy the most appropriate way is to use custom environment value. For simplicity let's use ResetDefault from https://stackoverflow.com/a/61847419/12299030 (you can rename it in your code)
So required modifications:
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
.environment(\.resetDefault, $showOnBoarding)
}
and in child view
struct TabDetailsView: View {
#Environment(\.resetDefault) var showOnBoarding
// .. other code
Button(action: {
self.showOnBoarding.wrappedValue.toggle()
}) {
Image(systemName: "xmark.circle.fill")
Text("Close")
}

SwiftUI how to set image for NavigationBar titleView like in UIKit?

I want to set an image in the titleView of NavigationBar in SwiftUI, as we do in UIKit
navigationItem.titleView = UIImageView(image: UIImage(named: "logo"))
this is how we do it in UIKit.
anyone know how to do it?
Here's how to do it:
Add SwiftUIX to your project.
Set your custom title view via View.navigationBarTitleView(_:displayMode:)
Example code:
struct ContentView: View {
public var body: some View {
NavigationView {
Text("Hello World")
.navigationBarTitleView(MyView())
}
}
}
Simple, Just add your root view into ZStack with top alignment and add your custom center view after root view
struct CenterNavigattionBar: View {
var body: some View {
ZStack(alignment: .top){
//Root view with empty Title
NavigationView {
Text("Test Navigation")
.navigationBarTitle("",displayMode: .inline)
.navigationBarItems(leading: Text("Cancle"), trailing: Text("Done"))
}
//Your Custom Title
VStack{
Text("add title and")
.font(.headline)
Text("subtitle here")
.font(.subheadline)
}
}
}
}
Before Image
After Image
Just use a toolbar.
You can add any views
import SwiftUI
struct HomeView: View {
// MARK: - Initializer
init() {
let appearance = UINavigationBar.appearance()
appearance.isOpaque = true
appearance.isTranslucent = false
appearance.barTintColor = UIColor(named: "background")
appearance.shadowImage = UIImage()
}
// MARK: - View
// MARK: Public
var body: some View {
NavigationView {
VStack(spacing: 20) {
Text("Hello")
Text("Navigation Bar Test")
}
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(leading: leadingBarButtonItems, trailing: trailingBarButtonItems)
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("Title").font(.headline)
Text("Subtitle").font(.subheadline)
}
}
}
}
}
// MARK: Private
private var leadingBarButtonItems: some View {
Button(action: {
}) {
Text("Left Button")
.font(.system(size: 12, weight: .medium))
}
}
private var trailingBarButtonItems: some View {
HStack {
Button(action: {
}) {
Text("R1\nButton")
.font(.system(size: 12, weight: .medium))
.multilineTextAlignment(.center)
}
Button(action: {
}) {
Text("R2\nButton")
.font(.system(size: 12, weight: .medium))
.multilineTextAlignment(.center)
}
}
}
}
Currently, you can't.
There are two overloads for .navigationBarTitle(), taking either a Text view or a type conforming to StringProtocol. You can't even pass in a modified view like Text("Title").font(.body). This would be a great feature, I'd submit a feature request: http://feedbackassistant.apple.com
Maybe this works for you?
Basically:
Use GeometryReader to get the width of the screen
Have NavigationBarItems(leading: HStack {Spacer() Image("name").resizable().frame(width:..., height: ..., alignment: .center Spacer()}.frame(width:geometry.size.width)
Example code:
struct ContentView: View {
var body: some View {
NavigationView {
GeometryReader { geometry in
Text("Hello, world!")
.padding()
.navigationTitle("test")
.navigationBarItems(leading: HStack {
Spacer()
Image("money")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
Spacer()
}
.frame(width: geometry.size.width)
)
}
}
}
}
Try this...
How to put a logo in NavigationView in swiftui?
This shows how to handle adding an Image to NavigationView in SwiftUI. Hope it helps.