List views jittering in SwiftUI - swiftui

I have a master detail view that navigates a series of sequential lists using totally vanilla SwiftUI and I'm noticing two things.
The list rows width jitters when you access one via navigation link?
The .navigationBarTitle isn't visible until the new view is completely on screen?
Seems like neither of these things are suppose to happen? Wonder if anyone has any ideas (video and code attached).
Video of the issues: https://www.dropbox.com/s/5jq3e8chay6hsy5/jitter.mov?dl=0
UserList.swift:
import SwiftUI
struct UserList: View {
var body: some View {
NavigationView {
List(userData) { this in
NavigationLink(destination: CityList(user: this, cities: this.cities)) {
UserRow(user: this)
}
}
.navigationBarTitle(Text("Users"))
}
}
}
UserRow.swift:
import SwiftUI
struct UserRow: View {
var user: UserModel
var body: some View {
VStack(alignment: .leading) {
Text(user.firstName + " " + user.lastName)
.font(.headline)
}
}
}
CityList.swift:
import SwiftUI
struct CityList: View {
var user: UserModel
var cities: [CityModel]
var body: some View {
List (cities) { this in
NavigationLink(destination: TownList(city: this, towns: this.towns)) {
CityRow(city: this)
}.navigationBarTitle(Text(self.user.firstName + self.user.lastName))
}
}
}
CityRow.swift:
import SwiftUI
struct CityRow: View {
var city: CityModel
var body: some View {
VStack(alignment: .leading) {
Text(city.name)
.font(.headline)
}
}
}

Related

Swift Tab view show more than one page 3 or 5 pages

I am trying to view List of objects in swiftui using Tabview, can I view more than one tab at same time??
You can check my code here:
import SwiftUI
#available(iOS 14, *)
struct CustomListWithPosition: View {
#Binding var itemsList: [ItemForPicker]
#Binding var selectedId: Int
#State private var visibleRows: [ItemForPicker] = []
var body: some View {
TabView(selection: $selectedId) {
Group {
ForEach(itemsList, id:\.id) { item in
Text("\(item.title)")
.frame(height: 44)
.foregroundColor(selectedId == item.id ? .yellow : .black)
.id(item.id)
.tag(item.id)
}
}
.rotationEffect(Angle(degrees: -90))
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.rotationEffect(Angle(degrees: 90))
.frame(height: 200)
}
}
struct ItemForPicker : Hashable {
var id: Int
var title: String
}
Thanx for your time.
You can surely view multiples view at the same time with TabView(), but displaying multiple views should not use with TabView() as it is not an ideal for viewing multiple views in the same screen; it would break the main purpose of TabView().
example:
you can do it like this, but it is not good.
var body: some View {
//not an ideal to do it
TabView {
HStack {
Group {
//display your objects
}
}
}
}
You should use List{}, VStack{}, ScrollView{}, HStack{} to display multiple views in your main view instead.

Why watchOS picker always shows "ScrollView contentOffset binding has been read" warning?

Bare minimum picker test app for watchOS.
import SwiftUI
#main
struct PickerTestApp: App {
var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
}
}
}
ContentView
import SwiftUI
struct ContentView: View {
var body: some View {
VStack{
NavigationLink(destination: DistanceSelectView()) {
Text("Next screen")
}
}
}
}
DistanceSelectView
import SwiftUI
struct DistanceSelectView: View {
#State var Age = 1
var body: some View {
VStack {
Picker(selection: $Age, label: Text("Select your age.[\(Age)]")) {
ForEach(10 ..< 100, id: \.self) { num in
Text("\(num)")
}
}
}
}
}
When run, and "Next screen" NavigationLink is pressed, it always displays the following warning:
"ScrollView contentOffset binding has been read; this will cause grossly inefficient view performance as the ScrollView's content will be updated whenever its contentOffset changes. Read the contentOffset binding in a view that is not parented between the creator of the binding and the ScrollView to avoid this."
What I'm doing wrong here?

SwiftUI list does not scroll using 2-finger swipe on trackpad

I have been testing this simple SwiftUI code: It has a list in ContentView. When a cell of the list is tapped, it pushes a SecondList into the navigation stack. When this SwiftUI code was run on a real iPad with a trackpad, I used 2-finger swipe to scroll the list up and down. The list in ContentView scrolls smoothly. However, for SecondList, it may freeze randomly and thereafter not responding.
It also failed in a UIKit project, where I replaced a UINavigationView with this ContentView using UIHostingViewController.
It was testing it with iPadOS 14.5 on both Simulator and iPad Pro hardware with Magic Keyboard.
How do I fix this? Thank you.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0..<30, id: \.self) { index in
NavigationLink(
destination: SecondList(),
label: {
Text(String(index))
})
}
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct SecondList: View {
var body: some View {
List {
ForEach(0..<30, id: \.self) { index in
Text(String(index))
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Use a scrollView
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0..<30, id: \.self) { index in
NavigationLink(
destination: SecondList(),
label: {
Text(String(index))
})
}
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct SecondList: View {
var body: some View {
scrollView {
List {
ForEach(0..<30, id: \.self) { index in
Text(String(index))
}
}
}
}
}

SwiftUI .shadow blocks List scroll gesture for all but first List {}. Why?

if I place 2 or more Lists with items in VStack or HStack and give the Vstack .shadow attribute, only the first List is scrollable and receives "gesture" events. Anybody has an idea why and is this intended behaviour? Seems like a bug to me. Tried on Xcode and device with iOS 14 and 14.+
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
ListView1()
ListView2()
}
.shadow(radius: 5)
}
}
struct ListView1:View {
var values=["1","2","3"]
var body: some View {
List {
ForEach(values, id: \.self) { (value) in
Text("Value \(value)")
}
}
}
}
struct ListView2:View {
var values=["5","6","7"]
var body: some View {
List {
ForEach(values, id: \.self) { (value) in
Text("Value \(value)")
}
}
}
}
Use compositingGroup() for solving issue!
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
ListView1()
ListView2()
}
.compositingGroup() // <<: Here!
.shadow(radius: 5)
}
}

Multi Level Navigation SwiftUI

I have a master detail application I'm working on in SwiftUI but once on the 1st DetailView, NavigationLink in the NavBar no longer works. I wrote this as a simple demonstration:
struct NavView: View {
var body: some View {
NavigationView {
NavigationLink(destination: Layer()) {Text("Go to Layer 1")}
}
}
}
struct Layer: View {
var body: some View {
Text("Welcome to Layer 1")
.navigationBarItems(trailing: NavigationLink(destination: AnotherLayer()) { Text("Go to Layer 2") })
}
}
struct AnotherLayer: View {
var body: some View {
Text("Welcome to Layer 2")
}
}
Everything renders and you can tap the navigationBarItem in Layer but nothing happens.
What's going on here? How can I access AnotherLayer?
A NavigationLink used as a navigationBarItem will not work no matter if you use it in the first or second level but a NavigationDestinationLink would solve the problem.
import SwiftUI
struct TestSwift: View {
var body: some View {
NavigationView {
NavigationLink(destination: Layer()) {Text("Go to Level")}
}
}
}
struct Layer: View {
let detailView = NavigationDestinationLink(AnotherLayer())
var body: some View {
VStack {
Text("Text")
}
.navigationBarItems(trailing:
Button(action: {
self.detailView.presented?.value = true
}, label: {
Text("Present Now!")
})
)
}
}
struct AnotherLayer: View {
var body: some View {
Text("Hello")
}
}