In iOS 15, the following code:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 0) {
ScrollView(.horizontal) {
HStack{ForEach(0 ..< 10, id: \.self) {Text("Item\($0)")}}
}
Image(systemName: "clock").resizable()
.padding(.top, -50).frame(height: 50)
.contentShape(Rectangle())
.clipped()
.onTapGesture {print("good")}
}
}
}
It happens that the ScrollView can't be scrolled because the bottom Image overlays it.
How can we scroll the ScrollView?
The clock view is eating the taps. You need to make the clock ignore taps by adding this:
.allowsHitTesting(false)
like this:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 0) {
ScrollView(.horizontal) {
HStack{ForEach(0 ..< 10, id: \.self) {Text("Item\($0)")}}
}
Image(systemName: "clock").resizable()
.padding(.top, -50).frame(height: 50)
.contentShape(Rectangle())
.clipped()
.allowsHitTesting(false)
}
}
}
Related
Does anyone know how to make the following view in SwiftUI?
HStack:
[ blank logo(centered) Skip(text)]
So I have the following HStack:
Zstack(alignment: .topLeading) {
VStack{
HStack {
Image("onboarding-logo")
.resizable()
.scaledToFit()
.frame(width: 150.0, height: 150.0)
.padding(.top, 35)
}
}
}
Does anyone know how I can have a "Skip" text in the top right corner of the screen, but also keep my logo centered and not have anything on the left side? I've tried Spacers and all, but I'm having no luck.
I would like to click "Skip" and then lead to another view.
There are many ways to achieve this. Here I have used LazyVGrid since other answers based on Stacks
struct ContentView: View {
var body: some View {
VStack {
LazyVGrid(columns: [GridItem(), GridItem(), GridItem()], content: {
Spacer()
Image(systemName: "star.fill")
.frame(width: 150, height: 150, alignment: .center)
.border(.gray)
Button(action: {
}, label: {
Text("Skip")
})
})
.border(.gray)
Spacer()
}
}
}
Is this the screen configuration you want?
The Zstack is used to center the Hstack into which the image is placed, and the new HStack uses a spacer to move the Text to the right.
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
VStack {
HStack(alignment: .center) {
Image("farnsworth")
.resizable()
.scaledToFit()
.frame(width: 150.0, height: 150.0)
}
Spacer()
}
VStack {
HStack {
Spacer()
Button {
// do Something...
} label: {
Text("Skip>>")
.padding(.top, 10)
}
}
Spacer()
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I have this example. Why is there this space at top and bottom of the VStack? The borders of the inner views doesn't seem to be as high as the border of the VStack. I think it has something to do with the LazyHGrid!? Thanks for an answer.
struct ContentView: View{
let names = ["house","creditcard"]
var body: some View{
VStack{
Text("skldfjsjf")
Text("klsadjf")
Text("lksajf")
ScrollView(.horizontal){
LazyHGrid(
rows: [GridItem(.flexible(minimum: 40)),GridItem(.flexible(minimum: 40))],
spacing: 10) {
ForEach(names, id: \.self) { icon in
Image(systemName: icon)
.padding()
}
}
.border(Color.orange)
}
.border(Color.green)
}
.frame(width: UIScreen.main.bounds.width * 0.9)
.border(Color.black)
}
}
I'm new to SwiftUI, but I think you want the content in your VStack to be top hugging?
struct ContentView: View {
let names = ["house","creditcard"]
var body: some View{
VStack (spacing:0) { //THIS HERE FOR NO SPACE FOR VSTACK INTERNAL VIEWS
Text("skldfjsjf")
Text("klsadjf")
Text("lksajf")
ScrollView(.horizontal){
LazyHGrid(
rows: [GridItem(.flexible(minimum: 40)),GridItem(.flexible(minimum: 40))],
spacing: 10) {
ForEach(names, id: \.self) { icon in
Image(systemName: icon)
.padding()
}
}
.border(Color.orange)
}
.border(Color.green)
Spacer() //THIS HERE TO MAKE IT TOP HUGGING
}
.frame(width: UIScreen.main.bounds.width * 0.9)
.border(Color.black)
}
}
I know this has been solved in iOS 14 but my current project is in iOS 13 and we have to release it fast. I tried multiple approach from stack but no luck. I just want to click a button and scroll to the bottom of the ScrollView, thats it. I was surprised there is not built in function in SwiftUI for this !!!
struct ContentView: View {
var items = [Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple, Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple]
var body: some View {
ZStack {
ScrollView(Axis.Set.vertical, showsIndicators: false) {
VStack {
ForEach(self.items, id: \.self) { item in
// 3.
Circle()
.fill(item)
.frame(width: 100, height: 100)
}
}
}
VStack {
Spacer()
HStack {
Spacer()
Button(action: {
// scroll to bottom
}) {
Text("Button")
}
}
.padding(.trailing, 20)
.padding(.bottom, 20)
}
}
}
}
If anybody could help
After a few hours search i found this amazing library that does exactly as you want
ScrollView{ proxy in
Button("click"){
proxy.scrollTo(200)
}.foregroundColor(.red)
ForEach(0..<1000){ index in
Text("\(index)")
.scrollId(index)
}
}
Not sure if this is the right way to accomplish having access to NavigationLink throughout my app, but I placed my NavigationBar in my root view, which happens to be the tab controller. See code below.
import SwiftUI
import Firebase
import Combine
struct ContentView: View {
#EnvironmentObject var session: SessionStore
func getUser() {
session.listen()
}
var body: some View {
NavigationView {
Group {
TabView {
ExploreView().tabItem {
Image(systemName: "house.fill")
Text("Explore")
}.tag(1)
FestivalsView().tabItem {
Image(systemName: "globe")
Text("Festivals")
}.tag(2)
MapView().tabItem {
Image(systemName: "map")
Text("Map")
}.tag(3)
ProfileView().tabItem {
Image(systemName: "person.crop.circle.fill")
Text("Profile")
}.tag(4)
}
.accentColor(Color("wdwPurple"))
.edgesIgnoringSafeArea(.top)
}.onAppear(perform: getUser)
}
}
}
However, within my ExploreView, the NavigationBar does not appear, and content floats under the status bar as shown in this image.
Here's the code for ExploreView
import SwiftUI
import Firebase
import Combine
import FirebaseFirestore
import UIKit
struct ExploreView: View {
let db = Firestore.firestore()
var model = Passport.all()
var body: some View {
VStack {
ScrollView (.vertical, showsIndicators: false) {
Header()
.padding(.horizontal, 24)
HStack {
Image("Ad_Banner")
.resizable()
.scaledToFill()
.frame(minWidth: 0, maxWidth: 366)
.padding(.bottom, 5)
}.padding(.horizontal, 24)
HStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
NavigationLink (destination: EventsView()) {
ExploreBoxes(tileLabel: "Events", tileIcon: "calendar")
.padding(.leading, 24)
.padding(.trailing, 10)
}
NavigationLink (destination: FavoritesView()) {
ExploreBoxes(tileLabel: "Favorites", tileIcon: "heart.fill")
.padding(.trailing, 10)
}
NavigationLink (destination: ParkMapsView()) {
ExploreBoxes(tileLabel: "Park Maps", tileIcon: "mappin.and.ellipse")
.padding(.trailing, 10)
}
}.frame(height: 180)
}
}
NavigationLink (destination: AboutView()) {
HStack {
Image("Image_Passports_Learn")
.renderingMode(.original)
.resizable()
.scaledToFill()
.frame(minWidth: 0, maxWidth: 366)
.cornerRadius(4)
}.padding(.horizontal, 24)
.padding(.bottom, 90)
}
}.navigationBarTitle(Text(""))
Spacer()
}.edgesIgnoringSafeArea(.bottom)
.background(Color("bodyBackground"))
}
}
This doesn't really work (as you've already discovered.) Similarly, in UIKit, this also wouldn't work. You need to create NavigationViews for each tab that you have. Typically, your TabView is your top-level view, and each tab can be wrapped in a NavigationView. Once you do that, you likely don't need to ignore top edge safe areas, either, as your NavigationView will be in the correct spot and properly communicate where the bar ends to its subviews.
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.