Closed andriy-appuchino closed 2 years ago
Hi @andriy-appuchino. I don't think I ever considered the Digital Crown but it should be simple enough. I'll take a look at it next week
@fermoya I haven't been able to find a solution, so I'll be waiting to see if you manage to implement it. Thanks a lot.
By the way, I just tried to do something myself, I managed to get it to work, but it works a little clunky, not like the native scroll on watchOS.
@StateObject var page: Page = .first()
var items = Array(0..<10)
@State var scrollAmount = 0.0
var body: some View {
Pager(page: page,
data: items,
id: \.self,
content: { index in
// create a page based on the data passed
Text("Page: \(index)")
})
.vertical()
.focusable(true)
.digitalCrownRotation($scrollAmount, from: 0, through: 10, by: 1, sensitivity: .low, isContinuous: false, isHapticFeedbackEnabled: true)
.onChange(of: scrollAmount) { newValue in
withAnimation {
page.update(.new(index: Int(newValue)))
}
}
}
@andriy-appuchino I'm not sure how this would work. digitalCrownRotation
isn't like a DragGesture
that has an onEnded
callback. Therefore, you can leave Pager
stuck in between 2 pages. This works great with a ScrollView
but Pager
isn't just a ScrollView
. See video below for more info:
@fermoya Look at my example, the important part is to set from: 0, through: 10, by: 1
. Where the through
value is the number of pages.
When rotating the crown and the value is fractional, you need to move the pages in the same way as you did with the drag gesture. But when you stop rotating the crown, the value will automatically go to a non-fractional value, which will work like onEded
, and will already be stopped on a specific page.
@fermoya could you try please?
Oh I see now what you mean. I'll come back to you shortly
@andriy-appuchino check out 2.4.0-beta.1. Notice that this works with watchOS 7.0
onwards
@fermoya Thank you for your efforts. I tried it, but it works about the same as my example. I'll try to clarify. Now when the crown rotates, the content does not move, but only after stopping, with some delay. It's not like the digital crown works on a watch. My expectation is that when rotating the crown, the content will also move, as if you are using a drag gesture, and then it centers the page. Could you improve this?
Here I made an example to demonstrate the logic I mean:
var body: some View {
GeometryReader { proxy in
List {
Group {
Color.blue
Color.green
Color.yellow
Color.orange
Color.red
}
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.frame(height: proxy.size.height)
}
.listStyle(.elliptical)
}
}
You can try this code for yourself. If you do not have an Apple Watch, then on the watch simulator a digital crown rotating is triggered by moving two fingers.
@andriy-appuchino I've been testing in a simulator, didn’t you see my first video? I haven’t merely copy-pasted your example if that’s what you suggest 😅
digitalCrownRotation
doesn’t work the same as DragGesture
as you imply. DragGesture
has an onEnded
callback (or alternatively, a GestureState
that resets). digitalCrownRotation
doesn’t, it just updated a Binding
. There’s no way to know when the rotation finished. So to ensure the page is centered I can just update the page index.
Any suggestions are more than welcome but this is the best it can be done as far as I can see.
Feel free to fork the repo, peek the code (PagerContent.body
), make changes and send a PR.
Well, yes, that's right. When the value changes to a fractional, then you need to move the content as you do with a drag gesture, and when the value becomes a non-fractional number, then just consider it fired onEnded.
print
the value observed in onChanged
, it's always a fractional! What you suggest is already done. Whenever the rotation goes over 0.5
, page index is incremented/decremented.
All in all, it can't be done in a linear fashion so to speak, unfortunately. An onEnded
callback or any other workaround would be needed
OK, thank you. I already made a fork, I'll try to figure it out. I'll let you know if it works.
Thanks @andriy-appuchino , all help is much appreciated. Keep me posted, I'd like to make a release within the next days. If you find some possible improvement I'll include it
@fermoya I managed to do it, I can't wait for you to try https://github.com/fermoya/SwiftUIPager/pull/268
new 2.4.0-beta.2 pushed
Great, it works as it should! 🎉 Thank you.
@fermoya by the way, when will the release be?
I'll make a release within 2-3 days tops most. I want to see if I can resolve an issue with a pipeline, first.
Anyway, I'll make a comment here when the new version is out
@fermoya I caught a bug.
Initial:
Steps:
Expectations: Nothing should happen.
Result: The page bounces, the position indicator on the right shows movement from page 1 to page 2.
After switching the page with a swipe, you need to change the state of the digital crown digitalCrownPageOffset
, you apparently missed it. It was in my PR, you can see how I did it.
Should be solved in beta-4
There was another problem on watchOS. If Pager
is in TabView
like in an example, then switching between tabs from left to right very often does not work. Probably Pager
is blocking gestures horizontally somewhere.
struct ContentView: View {
enum Tab {
case controls, main, player
}
@State private var selection: Tab = .main
@StateObject var page: Page = .first()
var items = Array(0..<2)
var body: some View {
TabView(selection: $selection) {
ControlsView()
.tag(Tab.controls)
Pager(page: page,
data: items,
id: \.self,
content: { index in
Text("Page: \(index)")
})
.vertical()
.tag(Tab.main)
NowPlayingView()
.tag(Tab.player)
}
.tabViewStyle(PageTabViewStyle())
}
}
@andriy-appuchino please open a new ticket, I think it's unrelated with this thread.
seems to be working for me anyways:
@fermoya When there is only Text on the page, the problem is less noticeable because the swipe is blocked only in the text area. I created an issue https://github.com/fermoya/SwiftUIPager/issues/274 and attached a project where the pages are filled with color. There is a very high reproducibility.
Hello. Great job! But I ran into a problem that the pager does not respond to moving the digital crown on the Apple Watch, as this usually works with ScrollView. Can I somehow enable digital crown support?