SwiftUI NavigationSplitView on iPad: remove accent from selected item in Sidebar - ios

I am adopting NavigationSplitView for an app to be used on an iPad as well as on an iPhone.
In my code below, I want to highlight the the selected item in the Sidebar only with the word "Selected".
When running for iPad Air 5th generation, the Sidebar appears differently between the preview and the simulator:
In the preview, the behaviour is exactly what I want: the word "Selected" indicates the item visible in the detail view (see picture below without blue border).
However, when running on the simulator, an accent rectangle is visible around the selection (see picture below with blue border). My goal is to remove this rectangle.
In fact, if we remove the .listRowBackground() modifier, in the preview the accent is light gray, in the simulator is blue.
Some things I tried:
Replacing .listRowBackground(EmptyView()) with .listRowBackground(Collar.clear): no success.
Using .accentColor(.clear): it does not work (the rectangle gets white), and moreover it is being deprecated, so I want to avoid it.
Adding .tint(.clear) and listItemTint(.clear): no success.
Replacing List with ForEach, but then I have to re-create the layout of the rows, and the result is not the same.
I need to keep the "yellow" background.
Does anyone know how to remove that rectangle?
My code:
struct MyView: View {
#State private var selected: MyContent?
let list = [MyContent("First"), MyContent("Second"), MyContent("Third")]
var body: some View {
NavigationSplitView {
List(list, selection: $selected) { item in
NavigationLink(value: item) {
HStack {
Text(item.title)
Spacer()
Text(selected == item ? "Selected" : "")
}
.foregroundColor(.primary)
}
.listRowBackground(EmptyView())
}
.scrollContentBackground(.hidden)
.listStyle(.plain)
.background(.yellow)
} detail: {
if let selected {
Text("Detail of \(selected.title)")
}
}
}
}
struct MyContent: Identifiable, Hashable {
let id = UUID()
let title: String
init(_ title: String) {
self.title = title
}
}
What I want to achieve (OK in the preview):
The rectangle I want to remove (running on the simulator):
Deploying for iOS 16.0 on Xcode 14.

Related

Text selection breaks scrolling

I'm trying out iOS 15 with Xcode Beta 2, and I'm using the new textSelection feature for Text.
However, if you enable text selection and put the Text objects in a List, and try scrolling on the text, nothing happens. However, disabling the text selection allows scrolling anywhere on the list.
Here is some reproducible code:
struct ContentView: View {
#State var data = (0..<100).map { "Test: \($0)" }
var body: some View {
List(data, id: \.self) { str in
Text(str)
.textSelection(.enabled)
}
}
}
If you try scrolling by moving your finger up on the area with text, nothing happens. However you can still scroll on the white areas.
Disabling text selection fixes this issue.
Are there any possible workarounds?

How can I make a SwiftUI List row background color extend the full width, including outside of the safe area

In a SwiftUI List, how can I make a list row background (set via .listRowBackground()) extend the full width of the view, even under the safe area? E.g. when running in landscape on a wide iPhone (iPhone 12 Pro Max, for example). Currently, the cell appears white on the far left of the cell until the start of the safe area.
Example code:
struct ContentView: View {
var body: some View {
List {
Text("Test")
.listRowBackground(Color(.systemGray3))
}.listStyle(GroupedListStyle())
}
}
This produces a UI as shown below. I would like the grey background of the cell to extend the full width of the device.
I've tried adding .edgesIgnoringSafeArea(.all) to the Text but it makes no difference.
The answer is to put .edgesIgnoringSafeArea([.leading, .trailing]) on the background Color itself, rather than the list item.
struct ContentView: View {
var body: some View {
List {
Text("Test").listRowBackground(
Color(.systemGray3).edgesIgnoringSafeArea([.leading, .trailing])
)
}.listStyle(GroupedListStyle())
}
}

How to change Background Color of a View containing a List back to White in SwiftUI

I am currently working with Lists in SwiftUI.
Problem: A default View in SwiftUI has a white background Color. However, when adding a List to it, the Background Color changes to systemGray6 while the List Cells take the white bgColor.
Goal: I would like to have a List with white bgColor and Cells with systemGray6 bgcolor.
I accomplished to change the Background Color of the List Rows :
List(users) { user in
// ...
}
.listRowBackground(Color(UIColor.systemGray6)
However, I can't find a solution for changing the Screen's bgColor back to white. I tried the obvious stuff like .background(Color.white).
Does anyone has a solution for this issue?
Thanks for your help.
you can change those colors as you wants, here a show example:(tested with Xcode 12.1 / iOS 14.1)
struct ContentView: View {
init() {
UITableView.appearance().backgroundColor = UIColor.white
}
var body: some View {
List
{
ForEach(0 ..< 20) { index in
Text("Row \(index)")
.listRowBackground(Color(UIColor.systemGray6))
}
}
}
}

SwiftUI - Button action draws on an image

Hobbyist ios coder here...
I have an old Objective C project I am trying to recreate in swiftui.
When I click a button, it draws a CGRect and fills in the peramiters of image source from the IBAction I wrote out that i can then drag arround the screen.
Old way I used to do it
How do i do this in SwiftUI?
My empty SwiftUI Button Code
I currently have an image drawn within a VStack that I can move arround and resize, but I want it to not exist on app load, but for it and others to be drawn on user request. IE button press.
I have no idea what it is im supposed to search for to find this answer as searching for button and image instantly gives me tutorials on how to add images to a button, not a button that draws a fresh interactable element on the view.
Thank you to anyone who can shed more light on this.
EDIT - On pressing the button a second time I need the image to spawn again so there would be multiple instances of it.
I'm not 100% sure if I understand this correctly, but it's simply a matter of displaying an image when a button is clicked?
You already said that you got an image with the desired behavior, but you don't want it to be there from the beginning. I think you are looking for an alternative in SwiftUI for addSubview, but there is no direct one.
What you might be looking for is #State in SwiftUI. Changing a #State variable will force your view to redraw itself. (There are more then just #State variables that to this)
You can draw your Image based on a condition. On your button click you could change the state variable that your condition is based on to redraw your view and to display your Image. I use the toggle() function in my example, so clicking the Button a second time will result in removing the image.
import SwiftUI
struct ContentView: View {
#State private var showImage = false
var body: some View {
VStack {
if showImage {
Image(systemName: "gear") // Your working image
}
Button(action: {
self.showImage.toggle()
}, label: {
Text("draw image")
})
}
}
}
Here is an example how you could add more and more Images when clicking the button again and again. I changed the Type of the #State variable to an array and then iterate over that array via a ForEach.
import SwiftUI
struct ContentView: View {
#State private var images: [UUID] = []
var body: some View {
VStack {
ForEach(images, id: \.self) { _ in
Image(systemName: "gear") // Your working image
}
Button(action: {
self.images.append(UUID())
}, label: {
Text("draw image")
})
}
}
}

NavigationBarTitle doesn't shrink text with minimumScaleFactor() or allowsTightening()

When using .navigationBarTitle on a NavigationView, adding the modifiers .minimumScaleFactor(0.5) or .allowsTightening(true) has no effect. The text is still cut off and remains same size.
My app displays a reference code and a few other bits of information in the navigation bar title and it fits perfectly on Plus sized iPhones but gets trimmed (...) on the smaller screen ones.
This information is quite vital to the operation of the app and we are already short of screen space so really don't have anywhere else to put this info.
With UIKit, I would have created a special TitleView to replace the title text in the NavigationBar, but that doesn't work in SwiftUI.
Is there any workaround for this?
Example:
struct ContentView: View {
let items = ["Chocolate", "Vanilla", "Strawberry", "Mint Chip",
"Pistachio"]
let title = "A long title that doesn't fit on a standard iPhone"
var body: some View {
NavigationView {
List(items, id: \.self) {
Text($0)
}
.navigationBarTitle(title, displayMode: .inline).minimumScaleFactor(0.5).allowsTightening(true)
}
}
}
ScreenShot from iPhone 8 Plus:
Screenshot from iPhone 8:

Resources