How to change Dimensions of an SwiftUI Default Button on MacOS? - swift

I want to change the behaviour of an SwiftUI Button so that two of them automatic get the same size.
But somehow I always only affect an ParentView of my View.
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Button("ABC", action: {return}).frame(maxWidth: .infinity).background(Color.green)
Button("EFCHHSJFJSJDNJS", action: {return}).buttonStyle(MorePaddingButtonStyle()).frame(maxWidth: .infinity).background(Color.yellow)
}.frame(maxWidth: .infinity)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
And it should be sized like this:
The example is located here in an GitHub repo.
Hope someone can help me to resize them with their background/shape (most likely for the default Button).

Use button with label
struct ContentView: View {
var body: some View {
HStack {
Button(action: { print("ABC") }) {
Text("ABC").frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}.buttonStyle(PlainButtonStyle()).background(Color.green)
Button(action: { print("EFCHHSJFJSJDNJS") }) {
Text("EFCHHSJFJSJDNJS").frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}.buttonStyle(MorePaddingButtonStyle()).background(Color.yellow)
}
}
}
The default button style can not set the width. It automatically set the width according to the button contains. So use PlayStyle or your own MorePaddingButtonStyle.

Related

How to make a SwiftUI view cover full screen

There is a SwiftUI file that is named Converter.swift that is opened when a button is clicked, the code is below, however how can I make the Converter SwiftUI cover the full screen when it is opened? I have tried .edgesIgnoringSafeArea(.all) which I put underneath
.sheet(isPresented: $converterSheetVisible) {
Converter()
however this is not working so I also tried
.frame(minWidth: .infinity, maxWidth: .infinity, minHeight: .infinity, maxHeight: .infinity)
but this is not working either.
import SwiftUI
import Firebase
import UIKit
struct ContentView: View {
#State private var converterSheetVisible = false
#AppStorage("log_status") var logStatus: Bool = false
var body: some View {
if logStatus{
DemoHome()
}else{
Login()
}
}
#ViewBuilder
func DemoHome()->some View{
VStack {
NavigationView {
NavigationStack{
Button("Enter"){
print("clicked")
self.converterSheetVisible.toggle()
}
}
.navigationTitle("Authenticated Account").font(.system(size: 15, weight: .regular))
.toolbar {
ToolbarItem{
Button("Logout"){
try? Auth.auth().signOut()
withAnimation(.easeInOut){
logStatus = false
}
}
}
}
}
.sheet(isPresented: $converterSheetVisible) {
Converter()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
sheet(isPresented:onDismiss:content:) does by definition not cover the whole screen. You can use fullScreenCover(isPresented:onDismiss:content:) instead. Like this:
.fullScreenCover(isPresented: $converterSheetVisible) {
Converter()
}

Change color view on SwiftUI

I can't find a solution to change my background color view, I tried a lot of options and nothing works.
I'm trying solutions but the isn't changing
There is my struct of the code:
struct ContentView: View {
var body: some View {
VStack {
Text("Trying ColorView")
.font(.largeTitle)
.bold()
Button("ColorView") {
}
}
.accentColor(Color.black)
}
}
First of all you have already mistakes in your posted code above, your XCode should normally tell you that.
Which view you want to change..?
This might be a solution... You can change it like you need it.
struct testViewTwo: View {
var body: some View {
NavigationView {
VStack {
VStack(spacing: -15) {
HStack {
HStack {
Text("Hello World")
}.background(Color.blue)
}.foregroundColor(Color.white)
}
}.background(Image("Background"))
}
}
}
You change a background color with the background modifier.
If you want to change the background color of the whole view, you should create a ZStack that spans the whole view with a background modifier.
ZStack {
...
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(Color(.blue)
You can simply use Color("Green") to change the color. Here's a sample.
var body: some View {
NavigationView{
VStack {
VStack(spacing: 15){
HStack {
Color("Green")
.edgesIgnoringSafeArea(.top)
}
}
}
}
}

How to disable resizability of Sidebar NavigationView in SwiftUI (MacOS)?

I'm new to Swift and I've been trying to build an app and learn as I go. I have a NavigationView that holds a List as a sidebar that renders the content as the user clicks. The bar between these two panes can be grabbed to allow the user to resize. This seems to be the default behavior of a NavigationView. I'm trying to find a way to disable it because I don't want the user to resize the sidebar.
struct Sidebar: View {
var body: some view {
List {
NavigationLink("First section", destination: FirstSection)
}
.frame(minWidth: 150, maxWidth: 150)
}
}
I also couldn't find a way to tell Swift that I want my List view to have a dynamic width that just fits the content. Just like it's done with CSS width: fit-content;
In the picture below, you can see that I was able to resize the sidebar to be almost half the screen. How to disable this behavior?
I do found a solution for that all you have to do is to set the destination width so that the sidebar can't be resized to the destination view for example like that ## consider the firstSection() as a View ##
Here the app main start
import SwiftUI
#main
struct macosTestApp: App {
var body: some Scene {
WindowGroup {
NavigationView {
SideBar()
}.toolbar {
// add the open/close sidebar navigation here
ToolbarItem(placement: .navigation) {
Button(action: toggleSidebar, label: { // 1
Image(systemName: "sidebar.leading")
})
}
}.frame(minWidth: 800, maxWidth: .infinity, minHeight: 600, maxHeight: .infinity, alignment: .center)
}
}
private func toggleSidebar() { // 2
NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
}
Here the sidebar and the navigationView
import SwiftUI
struct SideBar: View {
#State var isActiveView:Bool = true
var body: some View {
List {
NavigationLink("First section", destination: FirstSection().frame(minWidth: 750, maxWidth: .infinity, minHeight: 600, maxHeight: .infinity, alignment: .center),isActive: $isActiveView)
}
}
}
struct FirstSection: View {
var body: some View {
Text("Hello")
}
}
struct text_Previews: PreviewProvider {
static var previews: some View {
SideBar()
}
}
i was able to do it, in a weird way,
the first thing was to create an NSViewControllerRepresentable
so i was able to wrap an NSViewController in which i generate a 1X1 square view
because the NSViewController has the complete life cycle
i was able to write the code inside viewDidDisappear()
and toggle back the sidebar

SwiftUI Hide List Cell if its empty

I have a view in my Swift5 project where I use SwiftUI.
It's a List View.
Is there any way to add or remove a VStack from the list depending on a variable's data?
I can't place any logic in that part of the code so now I'm struggling.
List {
VStack {
Text(txt)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
}
VStack { // this view should be displayed or hidden if the data variable is 0
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .bottomLeading)
}.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
// here I check if there is any kind of data
if data.count == 0 {
print("Data is 0 so there is no image") // in this case I don't need the second VStack
} else {
print("Data is not 0 so there is an image") // in this case I need the second VStack
}
}
}
I've never tried to learn SwiftUI, because I got used to Swift5 so I don't have any kind of SwiftUI knowledge.
Heres a simple view, if you click on the button the first item inside the List disappears and if you click it again it shows up again:
To achive this I use a #State Variable. Changing the State of my view forces my view to reload. There are many nice articles online that describe the functionality of #State.
import SwiftUI
struct ContentView: View {
#State private var show = true
var body: some View {
VStack {
List {
if show {
Text("Text1")
}
Text("Text2")
Text("Text3")
}
Button(action: {
self.show.toggle()
}) {
Text("Hide Text1")
}
}
}
}
You can achive the same in your example:
if data.count == 0 {
self.show = false
} else {
self.show = true
}
you can use the show variable that you set based on the data to display a view.
if show {
Text("Text1") // Or whatever view you like
}

SwiftUI macOS NavigationView Cannot Highlight First Entry

I'm attempting to create a master/detail view on macOS with SwiftUI. When the master/detail view first renders, I'd like it to immediately "highlight" / "navigate to" its first entry.
In other words, I'd like to immediately render the following: master/detail first row highlighted
I'm using NavigationView and NavigationLink on macOS to render the master/detail view:
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: Text("detail-1").frame(maxWidth: .infinity, maxHeight: .infinity)) {
Text("link-1")
}
NavigationLink(destination: Text("detail-2").frame(maxWidth: .infinity, maxHeight: .infinity)) {
Text("link-2")
}
}
}
}
}
I've tried using both the isActive and the tag / selection options provided by NavigationLink with no luck. What might I be missing here? Is there a way to force focus on the first master/detail element using SwiftUI?
I came across this problem recently and after being stuck at the same point I found Apple's tutorial which shows that you don't use NavigationLink on macOS.
Instead you just create a NavigationView with a List and a DetailView. Then you can bind the List's selection and it works properly.
There still seems to be a bug with the highlight. The workaround is setting the selection in the next run loop after the NavigationView has appeared. :/
Here's a complete example:
enum DetailContent: Int, CaseIterable, Hashable {
case first, second, third
}
extension DetailContent: Identifiable {
var id: Int { rawValue }
}
struct DetailView: View {
#Binding var content: DetailContent?
var body: some View {
VStack {
Text("\(content?.rawValue ?? -1)")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct MainView: View {
#State var detailContent: DetailContent?
var body: some View {
NavigationView {
List(selection: $detailContent) {
Section(header: Text("Section")) {
ForEach(DetailContent.allCases) { item in
Text("\(item.rawValue)")
.tag(item)
}
}
}
.frame(minWidth: 250, maxWidth: 350)
.listStyle(SidebarListStyle())
if detailContent != nil {
DetailView(content: $detailContent)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
DispatchQueue.main.async {
self.detailContent = DetailContent.allCases.randomElement()
}
}
}
}