Why are those NavigationLinks not clickable? - swiftui

I have this code:
ScrollView () {
VStack(spacing: 0) {
ForEach(0..<10) {position in
NavigationLink(destination: DestinationView(position)) {
TimetableCellView(position)
}.padding(.all, 0.0)
}.padding(.all, 0.0)
}.cornerRadius(30.0).padding(.all)
}
It looks and feels as it should (besides the greyed out look of the TimetableCellViews in the list), but I can't click on the links. Any ideas how to solve?
Thx.

Related

ScrollView .scrollDismissesKeyboard(.interactively) feels weird

I set up a ScrollView like so:
ScrollView(.vertical) {
// ...
}
.scrollDismissesKeyboard(.interactively)
.safeAreaInset(edge: .bottom, spacing: 0) {
TextInputCellView(with: Color(hex: 0xf5f9fc)) { value in
vm.send(text: value)
}
}
The newly added scrollDissmissesKeyboard works, does however look and feel a little weird. Is this a bug or am i doing anything wrong ?

SwiftUI scroll to horizontal list item

I'm able to scroll to a vertical List item using ScrollViewReader proxy.
I tried doing something similar with Horizontal list, but it totally messed up the view.
Any suggestion, how this can be done ?
tia!
ScrollViewReader { proxy in
ScrollView(.horizontal, showsIndicators:false) {
ForEach(0..<items.count) { index in
Text(items[index].title)
.id(index)
.onTapGesture {
print("tapped \(index)")
}
}
.onAppear{
proxy.scrollTo(selectedIndex, anchor: .center)
}
}
}
ScrollView will not layout your views in a row just because you've specified .horizontal scrolling.
You need to specify HStack/LazyHStack explicitly inside ScrollView.
Another problem you may have encountered is that the scrolling position is not accurate, this can be fixed with DispatchQueue.main.async:
ScrollViewReader { proxy in
ScrollView(.horizontal, showsIndicators: false) {
HStack { // or LazyHStack
ForEach(0..<items.count) { index in
Text(items[index].title)
.id(index)
.onTapGesture {
print("tapped \(index)")
}
}
}
.onAppear {
DispatchQueue.main.async {
proxy.scrollTo(selectedIndex, anchor: .center)
}
}
}
}

SwiftUI: animating scroll on ScrollView programmatically?

I need to programmatically animate the scroll of a scrollview. The scrollview contains either an HStack or a VStack. Code I tested with is this:
ScrollViewReader { proxy in
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: spacing) {
ForEach(cids, id: \.self) { cid in
....
}
}
.onAppear {
withAnimation(Animation.easeInOut(duration: 4).delay(3)) {
proxy.scrollTo(testCid)
}
}
}
.frame(maxWidth: w, maxHeight: w / 2)
}
The scrollview does land on the item with the testCid, however, it does not animate.
As soon as the view comes on screen the scrollview is already on testCid...
How can I animate the scroll?
The interactive scroll works if you start it from somewhere else (f.e. Button action) but not from the onAppear modifier. I'd guess this is intentional behavior to prevent the user seeing the scrolling when the view appears (or a bug in SwiftUI...). An ugly workaround is to defer the animation with an DispatchQueue.main.async:
import SwiftUI
struct ContentView: View {
let words = ["planet", "kidnap", "harbor", "legislation", "soap", "management", "prejudice", "an", "trunk", "divide", "critic", "area", "affair"]
#State var selectedWord: String?
var body: some View {
ScrollViewReader { proxy in
VStack(alignment: .leading) {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 10) {
ForEach(words, id: \.self) { word in
Text(word)
.background(self.selectedWord == word ? Color.yellow : nil)
.id(word)
}
}
}
Button("Scroll to random word") {
withAnimation(Animation.easeInOut(duration: 1)) {
let word = words.randomElement()
self.selectedWord = word
proxy.scrollTo(word)
}
}
}
.onAppear {
DispatchQueue.main.async { // <--- workaround
withAnimation(Animation.easeInOut(duration: 1).delay(1)) {
let word = self.words.last
self.selectedWord = word
proxy.scrollTo(word)
}
}
}
}
.padding(10)
}
}

NavigationView / NavigationLink custom transition direction

I'm attempting to have a NavigationLink load a view from the bottom of the screen instead of transitioning from the right, but the "obvious" approach (using a .transition(.move(edge: .bottom))) doesn't seem to be having any effect.
The below is inside a NavigationView:
List {
ForEach(self.message, id: \.self) { message in
HStack(alignment: .center) {
MessageListCell(....)
}
}
}
and MessageListCell:
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 0) {
Text(person.firstName).lineLimit(1)
.foregroundColor(.main)
}
Spacer()
NavigationLink(destination: MessageDetail(otherPerson: otherPerson,
subject: subject,
profileHandler: { ProfileReducer($0) })
.transition(.move(edge: .bottom)),
tag: 1, selection: $action) {
NextButton("Proceed")
}
}
}
Tapping the NextButton consistently transitions from the right side of the screen instead of the bottom. I've tried variations on the above but I'm starting to think that transition might not be the right approach.

SwiftUI Drag events how do restrict to detect only horizontal/vertical scrolls

I have List (vertically scrolled) with nested ScrollView (or View that has dragging attached to it). I would like to have nested view onDrag() to be detected only on horizontal scrolling and not on vertical one. Vertical scrolling should be propagated to wrapper List.
Well, the following demo of horizontal scroll view inside vertical list should be working, and it is, unless List for now has known "refresh" defect. So... I decided to post it just for demo... maybe with next SwiftUI/iOS update it will be fixed automatically.
Also I provided variant of horizontal scroll view inside vertical scroll view, as a workaround to List issue. Hope any of those would be helpful.
So, demo code for "vertical drag anywhere propagated to vertical scrolling container, horizontal drag works only in horizontal scroll view"
A - Working variant of body based on vertical ScrollView (to replace in below module)
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .leading) {
ForEach (0..<20, id: \.self) { i in
VStack {
self.rowItem(index: i)
Divider()
}
}
}
}
}
B - "Working" variant with List (having refresh issue)
struct TestScrollInList: View {
var body: some View {
List {
ForEach (0..<20, id: \.self) { i in
self.rowItem(index: i)
}
}
}
func rowItem(index i: Int) -> AnyView {
if i % 2 == 0 {
return AnyView(self.plainItem(index: i))
} else {
return AnyView(self.scrollableItem(index: i))
}
}
func plainItem(index i: Int) -> some View {
Text("Plain item \(i)")
}
func scrollableItem(index i: Int) -> some View {
ScrollView (.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<10) { j in
RoundedRectangle(cornerRadius: 8)
.fill(j % 2 == 0 ? Color.green : Color.yellow)
.frame(width: 100, height: 100)
}
}
}
.frame(maxHeight: 110)
}
}
struct TestScrollInList_Previews: PreviewProvider {
static var previews: some View {
TestScrollInList()
}
}