How to set SwiftUI preview canvas background? - swiftui

I am working on a UI component which has a whitish back and is hard to see from the SwiftUI preview canvas.
Is there a way I can set the background of the preview canvas so I can see the render UI component with a light color background?

You actually don't need the rectangle with a ZStack:
static var previews: some View {
ZStack {
Color(.black)
SampleUI()
}
}
If you're previewing on an iPhone X or above, here's how you make the color display over the safe area:
static var previews: some View {
ZStack {
Color(.black).edgesIgnoringSafeArea(.all)
SampleUI()
}
}

I managed to achieve it with a workaround by using a ZStack with a Rectangle view.
static var previews: some View {
ZStack {
Rectangle()
.foregroundColor(.black)
SampleUI()
}
}

Related

Using a custom background behind NavigationStack in SwiftUI

This ought to be straightforward enough, but I cannot find out how to place a background behind a NavigationStack. With NavigationView, it was simply a matter of embedding in a ZStack with the background view called before the NavigationView (as described in an older post: How change background color if using NavigationView in SwiftUI?)
The same technique does not work for me with NavigationStack.
Here's what I have:
struct MyAngularGradient: View {
var body: some View {
ZStack {
AngularGradient(gradient: Gradient(colors: [.red, .orange , .yellow, .green, .cyan, .blue, .indigo, .purple, .red]), center: .leading)
AngularGradient(gradient: Gradient(colors: [.red, .orange , .yellow, .green, .cyan, .blue, .indigo, .purple, .red]), center: .leading)
.offset(x: -8)
}
.ignoresSafeArea()
}
}
var body: some View {
ZStack{
MyAngularGradient()
NavigationStack {
...
}
.navigationViewStyle(.stack)
} // end ZStack
FYI, I've used the same MyAngularGradient()in other apps (with NavigationView)
Any ideas? Thanks.
The closest I've managed to get so far is this:
struct MyView: View {
var body: some View {
NavigationStack {
ZStack {
Color.pink.ignoresSafeArea()
List {
NavigationLink("Hello") {
Text("Hello")
}
}
.navigationTitle("Title")
}
}
.scrollContentBackground(.hidden)
}
}
Which is somewhat dissatisfying for the following reasons:
When you scroll up the navigation bar appears, as expected, but ruins the effect imo.
I guess you can experiment changing this in a limited way using UINavigationBarAppearance() by updating it in the constructor of the view.
You can't apply a background to the whole app if you have multiple NavigationStackView based views in a TabView. (My example above was in a TabView)
When a new view is pushed on the stack the custom background disappears.
Only works on iOS 16+ due to the .scrollContentBackground(.hidden) modifier.
Does not work if you use ForEach to populate the List. Interestingly if you debug the hierarchy with and without the ForEach you'll see that SwiftUI adds a new view controller which is opaque in the case of ForEach.

TabView taking Top Space in SwiftUI

Hi I am currently working on swiftUI project. I am facing a very strange issue. Here is the code for my problem. As you can see that, this tabView is taking some space from the Top which is highlighted in Red Color. It should be All blue in the View.
Why it is taking that extra space from the Top?
Kindly Review the code and help me with this problem as i'm a beginner.
import SwiftUI
struct StackOverFlowView: View {
#State private var selection = 0
var body: some View {
ZStack() {
Color.red
TabView(selection: $selection) {
Color.blue
}
.tabViewStyle(PageTabViewStyle())
.edgesIgnoringSafeArea(.all)
}.ignoresSafeArea(.all)
}
}
struct StackPreview: PreviewProvider {
static var previews: some View {
StackOverFlowView()
}
}

How to change the Color of SwiftUI redacted shimmer effect

I added a shimmer effect for my home screen like the code below.
VStack{
TopView()
HomeView()
}
.redacted(.placeholder)
I got the output like the below image.
https://ibb.co/xFXQ2sk
the shimmer view showing color for the colored view but the normal view shows gray colored.
can i change the whole shimmer view into gray color without showing the colored view in shimmer?
One approach might be to adjust your custom subviews to respond to whether they're being asked to display as a redaction.
For example, if you have a view that adds a piece of text within a red background, e.g.:
struct LabelView: View {
var text: String
var body: some View {
Text(text)
.padding()
.background(Color.red)
}
}
you could then adapt it to use grey when being redacted:
struct LabelView: View {
#Environment(\.redactionReasons) var redactionReasons
var text: String
var body: some View {
Text(text)
.padding()
.background(redactionReasons.contains(.placeholder) ? Color.gray : Color.red)
}
}

SwiftUI - Catalyst translucent sidebar

Goal is to make a translucent sidebar on Mac Catalyst.
The code bellow gives a not translucent sidebar (image 1).
On Mac (not catalyst) the sidebar looks fine (image 2).
is it possible to have a translucent sidebar on Mac Catalyst?
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
//sidebar
List {
Label("Books", systemImage: "book.closed")
Label("Tutorials", systemImage: "list.bullet.rectangle")
}
.background(Color.clear)
.listStyle(SidebarListStyle())
//content
Text("Sidebar")
.navigationTitle("Sidebar")
}
}
}
You should select "Optimize Interface for Mac" in your target's General settings tab. Then the sidebar will be translucent.
Start with the AppDelegate main and follow Apple's tutorial re: UISplitViewController "Apply a Translucent Background to Your Primary View Controller".
https://developer.apple.com/documentation/uikit/mac_catalyst/optimizing_your_ipad_app_for_mac
In wrapping UISplitViewController in a UIViewControllerRepresentable, I wasn't able to get translucency, but did get full-height sidebar.
I figured out that using .background(Color.clear) on sidebar View makes possible translucent background even if ListStyle is not specified as SidebarListStyle(). Works in Xcode 13.1 for me
struct ContentView: View {
var body: some View {
NavigationView { // without wrapping to NavigationView it won't work
List { // can be VStack or HStack
Text("Hello, world!")
.padding()
}
.listStyle(SidebarListStyle()) // works with other styles
Text("")
}
}
}
struct YourApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.toolbar {
Button {
} label: {
Image(systemName: "gear")
}
}
.background(Color.clear) // 3 <-- MUST HAVE!
}
}
}

How do I set a background view's size equal to a foreground view's size?

I have a foreground view and a background view. The foreground view contains some text, images, and a couple of stack views. It automatically sizes itself and looks perfect. I want to add a background view that matches the automatic size of my foreground view. My background view is a View composed of some shapes.
Things I've tried:
If I use a ZStack, my background view sizes itself (filling the container).
If I overlay the background on top of the foreground, the background view has the correct size but it obscures the foreground view.
If I overlay the foreground view on top of the background view, the background view determines it's own size.
Code Sample
Foreground View
struct ForegroundView: View {
var body: some View {
HStack {
Image(systemName: "photo")
VStack(alignment: .leading) {
Text("Title")
Text("Subtitle")
}
Spacer()
Text("42")
}
}
}
struct ForegroundView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Background View
The background view is a progress bar.
struct ProgressBar: View {
#Binding var value: Float
var body: some View {
GeometryReader { gr in
ZStack(alignment: .leading) {
Rectangle()
.frame(width: gr.size.width,
height: gr.size.height)
.opacity(0.3)
.foregroundColor(Color(UIColor.systemTeal))
Rectangle()
.frame(width: min(CGFloat(self.value)*gr.size.width, gr.size.width),
height: gr.size.height)
.foregroundColor(Color(UIColor.systemBlue))
.animation(.linear)
}
}
}
}
struct ProgressBar_Previews: PreviewProvider {
static var previews: some View {
ProgressBar(value: .constant(0.5))
}
}
Things I Tried
struct Demo_Preview: PreviewProvider {
static var previews: some View {
Group {
// Attempt 1
ZStack {
ProgressBar(value: .constant(0.5))
ForegroundView()
}
// Attempt 2
ForegroundView().overlay(ProgressBar(value: .constant(0.5)))
// Attempt 3
ProgressBar(value: .constant(0.5)).overlay(ForegroundView())
}
}
}
The answer, it turns out, is quite simple: the background modifier.
struct Demo_Preview: PreviewProvider {
static var previews: some View {
Group {
ForegroundView().background(ProgressBar(value: .constant(0.5)))
}
}
}