hello i have an issue with my project on Xcode when I use navigation view, the window display not normally and appear on the right of the window already displayed,
here is the code.
NavigationLink(destination: Acceuil())
{
HStack{
Image("icone_connexion")
.font(.system(size: 15))
// .scaledToFill()
Text("se connecter")
.font(.system(size: 30))
}.cornerRadius(60)
.frame(width: 400, height: 60)
} .background(Capsule().fill(Color(red: 55/255, green: 66/255, blue: 114/255, opacity:1)))
.frame(width: 400, height: 60) //fin navigationlink
.buttonStyle(PlainButtonStyle())
I would like that the new window replace the older one:)
On macOS it is the standard behavior in NavigationView to show the views (parent view and destination view) next to each other: https://developer.apple.com/design/human-interface-guidelines/macos/windows-and-views/column-views/
If you don't want that you can do:
NavigationView {
...
}
.navigationViewStyle(.stack)
so I found this code
import SwiftUI
struct ContentView: View {
#State private var show = false
var body: some View {
VStack{
if !show {
RootView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.transition(AnyTransition.move(edge: .leading)).animation(.default)
}
if show {
NextView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.green)
.transition(AnyTransition.move(edge: .trailing)).animation(.default)
}
}
}
}
struct RootView: View {
#Binding var show: Bool
var body: some View {
VStack{
Button("Next") { self.show = true }
Text("This is the first view")
}
}
}
it work grate for me so thanks you for your help
Related
I'm trying to get the entirety of a row to be double clickable.
Here is my code:
import SwiftUI
let colourArray = ["red","blue","green"]
struct ContentView: View
{
var body: some View
{
List
{
ForEach (colourArray, id: \.self)
{ colour in
ArrayRow(colour: colour)
.gesture(TapGesture(count: 2).onEnded
{
print("double clicked")
})
.padding(.bottom, 15)
}
}
}
}
struct ArrayRow: View
{
let colour: String
var body: some View
{
HStack(alignment: .top)
{
Text(colour)
.frame(width: 150, alignment: .leading)
Text(colour)
.frame(width: 150, alignment: .leading)
Text(colour)
.frame(width: 150, alignment: .leading)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The double click works great, but only if you double click on the text. If you double click on the white space then nothing happens. How do I get the whole row to respond to the double click?
You can extend the tappable/clickable area with .contentShape
ArrayRow(colour: colour)
.contentShape(Rectangle())
.gesture(TapGesture(count: 2).onEnded
{
print("double clicked")
})
.padding(.bottom, 15)
I'm having some trouble with HSplitView on macOS, and I'm not sure if it's a bug or something I'm doing wrong.
I'm trying to create an app with a [Sidebar | Main Content | Inspector] layout. This is similar to the SF Symbols app, where you can view more information about a selected icon.
The approach I've taken is to have the Main Content and Inspector views be in an HSplitView. Having three views in a NavigationView only seems to use the Mail pattern of [List | List | Detail], which is not the layout I'm looking for.
The problem I'm seeing is that when I set a maxWidth on the Inspector view and drag the divider to the left, the Main Content view resizes to be smaller than the available space. The parent HSplitView doesn't resize, so I'm not sure if I'm using the wrong modifiers or using them in the wrong places.
I've setup a basic test case on github. If y'all could offer and help or guidance, that would be amazing.
Observed behaviour
Expected behaviour
import SwiftUI
struct A: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text("Pane A")
Spacer()
}
Spacer()
}
.frame(
minWidth: 200,
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .leading
)
.background(Color.red)
.foregroundColor(.black)
.layoutPriority(1)
}
}
struct B: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text("Pane B")
Spacer()
}
Spacer()
}
.frame(
minWidth: 200,
idealWidth: 250,
maxWidth: 300,
maxHeight: .infinity
)
.background(Color.purple)
.foregroundColor(.black)
}
}
struct ContentView: View {
var body: some View {
HSplitView {
A()
B()
}
.frame(
minWidth: 0,
maxWidth: .infinity,
maxHeight: .infinity
)
.background(Color.blue)
}
}e
Thanks!
I've had the same problem for several days, and I solved it in a flash.
Need to drag View
HSplitView {
View1()
View2()
}
Intuitively, we will set the maximum width of View1, but when SwiftUI drags, View1 exceeds the maximum width, it will display an inexplicable error
HSplitView {
View1()
.frame(maxWidth: 300)
View2()
}
Solutions
Set the minimum width of View2, and let View automatically fill all spaces. There will be no drag problem
HSplitView {
View1()
View2()
.frame(minWidth: 500)
}
Embedding one split view inside other may work.
Some problems arise if using GeometryReader.
HSplitView
{
View1()
HSplitView
{
View2()
View3()
}
}
I have a problem getting the correct alignment for two buttons (Cancel and OK) in a sheet using SwiftUI.
I want the two buttons to appear at the bottom of the sheet so that the two of them span the whole horizontal width of the sheet (minus padding).
I've found several answers (such as setting the maxWidth to .infinity or by putting the text contend of a button in a separate Text view and surrounding it by Spacers) but none of them seem to work for me. The only one that works somewhat is by creating my own ButtonStyle. But then I have to recreate the whole default ButtonStyle (different for default button, for day and night mode,...)
The code I have now is:
var body: some View {
VStack() {
...
HStack {
Button("Cancel",action: {
isPresented.toggle()
})
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.keyboardShortcut(.cancelAction)
.border(Color.red)
Button("OK", action: {
isPresented.toggle()
let newServer = Server(name: name, url: url, port: port, autoConnect: autoConnect)
do {
try model.add(server: newServer)
} catch {
print("Could not add server.")
}
})
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.keyboardShortcut(.defaultAction)
.border(Color.red)
}
.frame(maxWidth: .infinity)
.padding(.top, 20)
.border(Color.blue)
}
.padding()
.frame(minWidth: 300, maxWidth: 300)
}
This results in the following sheet:
I would like both buttons to fill the area surrounded by the red border.
I'm kinda at a loss on what to try next!
as the red borders show, the buttons do extend to fill the area.
To get the background gray as in the picture, you could use something like:
.background(Color(UIColor.systemGray4))
as the last modifier of each buttons.
Default button style is rendered around provided label content, so possible solution is to calculate needed width for button label dynamically and apply it explicitly.
Note: please also see my comment for alternate
Demo prepared with Xcode 12.5 / macOS 11.3
struct ContentView: View {
#State private var cancelWidth = CGFloat.zero
#State private var okWidth = CGFloat.zero
var body: some View {
VStack() {
Text("Demo here!")
HStack(spacing: 0) {
Button(action: {
}) { Text("Cancel").frame(width: cancelWidth) }
.frame(minWidth: 0, maxWidth: .infinity)
.background(GeometryReader {
Color.clear.preference(key: ViewWidthKey.self,
value: $0.frame(in: .local).size.width) })
.onPreferenceChange(ViewWidthKey.self) { self.cancelWidth = $0 }
.padding()
.border(Color.red)
.keyboardShortcut(.cancelAction)
Button(action: {
}) { Text("OK").frame(width: okWidth) }
.frame(minWidth: 0, maxWidth: .infinity)
.background(GeometryReader {
Color.clear.preference(key: ViewWidthKey.self,
value: $0.frame(in: .local).size.width) })
.onPreferenceChange(ViewWidthKey.self) { self.okWidth = $0 }
.padding()
.keyboardShortcut(.defaultAction)
.border(Color.red)
}
.frame(maxWidth: .infinity)
.padding(.top, 20)
.border(Color.blue)
}
.padding()
.frame(minWidth: 300, maxWidth: 300)
}
}
struct ViewWidthKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = value + nextValue()
}
}
I'm working on an app for iPad that is to be used to manage a personal cash budget. I'm working with XCode 12 building for iOS 14 using SwiftUI. I have most of the underlying MODEL work done, but I'm struggling with the UI. I've programmed in various languages since 1979. (Yes I' old and doing this is a hobby :-). I can not for the life of me figure out the technique to pop an edit/entry view over a parent view. As an example, I have an app the I also use that does just this. I'm attaching an image that shows what I'd like to be able to do. I've tried .overlay() and ZStack, but what I've tried just doesn't give me what I want. If you could look at the image I'm posting and point me in the right direction for even just for technique I'd be really appreciative....
Image of entry view popped over subview:
Image of subview before:
The image looks like the new view is being presented via the .sheet() modifier. This is the most common approach to present a view like this. I would just note that it looks slightly different on iPad (like the image above) vs iPhone (extends full width of screen).
struct Test: View {
#State var showSheet: Bool = false
var body: some View {
Text("Hello, World!")
.onTapGesture {
showSheet.toggle()
}
.sheet(isPresented: $showSheet, content: {
Text("Next view")
})
}
}
Alternatively, here are 2 other methods to present a sheet, which can be a little more customizable (custom animations/transitions) if required.
struct Test2: View {
#State var showSheet: Bool = false
var body: some View {
ZStack {
Text("Hello, World!")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onTapGesture {
showSheet.toggle()
}
if showSheet {
Text("Next view")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.animation(.spring())
.transition(.move(edge: .bottom))
}
}
}
}
struct Test3: View {
#State var showSheet: Bool = false
var body: some View {
ZStack {
Text("Hello, World!")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onTapGesture {
showSheet.toggle()
}
Text("Next view")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.opacity(showSheet ? 1.0 : 0)
.animation(.spring())
}
}
}
I am completely new to SwiftUI so I hope this is not a stupid question. In my project I have a home view (a map) and a Menu button in the top right corner. Upon clicking that button my menu is gonna slide in from the left. For each of the menu items I want to use NavigationLink to jump to the next detail views.
Now here is the problem: When I click on the menu items (eg. Payments) I get the view but my button and my map are still on top of that view and I cant get rid of it, or at least I dont know how.. :(.
I saw a few similar questions but I couldnt make it work for my case.
This is my view when the menu view is true
This is my problem view. When I click on eg. Payments I cant get rid of the Map and the button in that view
This is my HomeView (The Map and the button)code:
import SwiftUI
struct HomeView: View {
#State var showMenu = false
var body: some View {
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.showMenu = false
}
}
}
return GeometryReader { geometry in
ZStack(alignment: .leading) {
if self.showMenu {
SlideInMenuView()
.frame(width: geometry.size.width/1)
.transition(.move(edge: .leading))
}
HomeSupportView()
.frame(width: geometry.size.width, height: geometry.size.height)
.cornerRadius(20)
.scaleEffect(self.showMenu ? 0.8 : 1)
.offset(x: self.showMenu ? 150 : 0, y : self.showMenu ? 50 : 0)
.disabled(self.showMenu ? true : false)
MenuButton(showMenu: self.$showMenu)
}
.gesture(drag)
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
HomeView()
}
}
struct MenuButton: View {
#Binding var showMenu: Bool
var body: some View {
Button(action: {
withAnimation {
self.showMenu.toggle()
}
}){
Image(systemName: "line.horizontal.3")
.imageScale(.large)
.frame(width: 100, height: 60)
.background(Color.black)
.clipShape(Circle())
.opacity(0.8)
.foregroundColor(.white)
.rotationEffect(.degrees(self.showMenu ? 90 : 0))
.scaleEffect(self.showMenu ? 1.2 : 1)
}
.padding(.top, -380)
}
}
This is my menu view code with my try of making the NavigationLink work. I tried it on the "Payments" HStack in multiple versions but I just cant make it work
import SwiftUI
struct SlideInMenuView: View {
#State private var showingPaymentDetails = false
var body: some View {
NavigationView {
VStack(alignment: .leading) {
HStack {
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Profile")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 150.0)
HStack {
Image(systemName: "person.2.fill")
.foregroundColor(.gray)
.imageScale(.large)
Text("Matches")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
NavigationLink(destination:
PaymentDetailsView())
{
HStack {
Image(systemName: "creditcard")
.foregroundColor(.gray)
.imageScale(.large)
Text("Payments")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
}
HStack {
Image(systemName: "hammer")
.foregroundColor(.gray)
.imageScale(.large)
Text("Settings")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
Spacer()
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
.edgesIgnoringSafeArea(.all)
}
}
}
struct SlideInMenuView_Previews: PreviewProvider {
static var previews: some View {
SlideInMenuView()
}
}
If anyone knows how to help me out here...
Thank you very much in advance guys.
Stay healthy.
Cheers,
LeBob
#Chris: This is how I want it to be. I put in 4 consecutive screenshots with the respective clicks.
***** UPDATED ANSWER *****
thank you for your clarifying pictures
try this:
import SwiftUI
class Global : ObservableObject {
#Published var showMenu = true
#Published var showMenuButton = true
}
struct PaymentDetailsView : View {
#EnvironmentObject var global : Global
var body: some View {
Text("payment")
.onAppear() {
withAnimation() {
self.global.showMenuButton = false
}
}
.onDisappear() {
withAnimation() {
self.global.showMenuButton = true
}
}
}
}
struct HomeSupportView : View {
#EnvironmentObject var global : Global
var body: some View {
ZStack {
Rectangle().fill(Color.blue)
Text("home")
}
}
}
struct SlideInMenuView: View {
#EnvironmentObject var global : Global
#State private var showingPaymentDetails = false
var body: some View {
NavigationView {
VStack(alignment: .leading) {
HStack {
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Profile")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 150.0)
HStack {
Image(systemName: "person.2.fill")
.foregroundColor(.gray)
.imageScale(.large)
Text("Matches")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
NavigationLink(destination:
PaymentDetailsView().environmentObject(self.global))
{
HStack {
Image(systemName: "creditcard")
.foregroundColor(.gray)
.imageScale(.large)
Text("Payments")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
}
HStack {
Image(systemName: "hammer")
.foregroundColor(.gray)
.imageScale(.large)
Text("Settings")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
Spacer()
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
.edgesIgnoringSafeArea(.all)
}
}
}
struct SlideInMenuView_Previews: PreviewProvider {
static var previews: some View {
SlideInMenuView().environmentObject(Global())
}
}
struct ContentView: View {
#EnvironmentObject var global : Global
var body: some View {
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.global.showMenu = false
}
}
}
return GeometryReader { geometry in
ZStack(alignment: .leading) {
if self.global.showMenu {
SlideInMenuView()
.environmentObject(self.global)
.frame(width: geometry.size.width/1)
.transition(.move(edge: .leading))
.zIndex(3)
}
HomeSupportView()
.environmentObject(self.global)
.frame(width: geometry.size.width, height: geometry.size.height)
.cornerRadius(20)
.scaleEffect(self.global.showMenu ? 0.8 : 1)
.offset(x: self.global.showMenu ? 150 : 0, y : self.global.showMenu ? 50 : 0)
.disabled(self.global.showMenu ? true : false)
.zIndex((2))
MenuButton().environmentObject(self.global)
.zIndex(4)
}
.gesture(drag)
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(Global())
}
}
struct MenuButton: View {
#EnvironmentObject var global: Global
var body: some View {
Button(action: {
withAnimation {
self.global.showMenu.toggle()
}
}){
if self.global.showMenuButton {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
.frame(width: 100, height: 60)
.background(Color.black)
.clipShape(Circle())
.opacity(0.8)
.foregroundColor(.white)
.rotationEffect(.degrees(self.global.showMenu ? 90 : 0))
.scaleEffect(self.global.showMenu ? 1.2 : 1)
} else {
EmptyView()
}
}
.padding(.top, -380)
}
}
SwiftUI has a zIndex() modifier that you can use to order the views.
This could help in your situation.