Status Update
Comments
ma...@google.com <ma...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-main
Author: Louis Pullen-Freilich <
Link:
Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling
Expand for full commit details
Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling
These APIs allow overscroll to have events dispatched to it by one component, and rendered in a separate component.
Fixes: b/266550551
Fixes: b/204650733
Fixes: b/255554340
Fixes: b/229537244
Test: OverscrollTest
Relnote: "Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling APIs - these APIs create a wrapped instance of the provided overscroll effect that doesn't draw / handle events respectively, which allows for rendering overscroll in a separate component from the component that is dispatching events. For example, disabling drawing the overscroll inside a lazy list, and then drawing the overscroll separately on top / elsewhere."
Change-Id: Idbb3d91546b49c1987a041f959bce4b2b09a9f61
Files:
- M
compose/foundation/foundation/api/current.txt
- M
compose/foundation/foundation/api/restricted_current.txt
- M
compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/OverscrollDemo.kt
- M
compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/OverscrollSample.kt
- M
compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt
- M
compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Overscroll.kt
Hash: f64e25b7a473c757d080521e7dd97b3f6670f60d
Date: Fri Nov 01 18:43:56 2024
sa...@squareup.com <sa...@squareup.com> #3
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.compose.foundation:foundation:1.8.0-alpha06
androidx.compose.foundation:foundation-android:1.8.0-alpha06
androidx.compose.foundation:foundation-jvmstubs:1.8.0-alpha06
androidx.compose.foundation:foundation-linuxx64stubs:1.8.0-alpha06
sa...@squareup.com <sa...@squareup.com> #4
Update: I tried using a side effect but with strange results. I am using the demo code shown in
For my first attempt, these two println
statements are printed infinitely:
LaunchedEffect(state.isTransformInProgress) {
println("Is transformation in progress? ${state.isTransformInProgress}")
if (!state.isTransformInProgress) {
println("Resetting offset")
state.animatePanBy(offset = -offset)
}
}
I assume this is because animatePanBy
is quickly switching isTransformInProgress
from true
to false
for running an empty animation, leading to the loop. It's funny that state.isTransformInProgress
is always evaluated to false
by the time the first print statement is executed.
If I add another condition to run the animation only for non-zero offsets, I get a slightly better result, but it still runs 2-3 times.
LaunchedEffect(state.isTransformInProgress) {
println("Is transformation in progress? ${state.isTransformInProgress}")
if (!state.isTransformInProgress && offset != Offset.Zero) {
println("Resetting offset")
state.animatePanBy(offset = -offset)
}
}
I also tried using a snapshotFlow
, but this suffers from a different problem: if the animation is interrupted with another gesture, the collect
operator stops receiving any more values. There might be a way to restart it, but I wasn't able to figure out a simple one.
LaunchedEffect(Unit) {
snapshotFlow { state.isTransformInProgress }
.distinctUntilChanged()
.filter { inProgress -> !inProgress }
.collect {
state.animatePanBy(offset = -offset, tween(1_000))
}
}
Do you see anything obvious that I might be missing?
ma...@google.com <ma...@google.com> #5
Yeah I think I was mistaken suggesting this as it will indeed flip back and forth, because that's the contract of the isTransformationInProgress. In fact, seems like you need an indication of the
I think what we should do is to add InteractionSource to the state, so that you can query specifically the Drag
interaction and launch against its change. Louis, wdyt?
lp...@google.com <lp...@google.com> #6
Yeah makes sense to add InteractionSource integration here, same as for things like ScrollState
sa...@squareup.com <sa...@squareup.com> #7
Will DragInteraction
be sufficient for querying fling velocity? I'm trying to think how would this work w.r.t nested scrolling.
lp...@google.com <lp...@google.com> #8
Nope, there won't be a way to get that kind of information currently, and I don't think DragInteraction
is the correct place for that sort of thing. If you specifically need velocity, I guess we need a specific callback / build your own implementation where you can reference this directly
sa...@saket.me <sa...@saket.me> #9
A callback would be great for compatibility with nested scrolling.
sa...@saket.me <sa...@saket.me> #10
On a second thought, a callback alone wouldn't be sufficient for enabling nested scrolling. Modifier.transformable()
consumes all events by default even if its content can't pan any further, preventing scrollable parents from showing overscroll effects. I can file a separate issue for that if you want.
lp...@google.com <lp...@google.com> #11
Ah I see, yes please file a separate bug. Probably transformable should just implement nested scrolling directly - if it did do that, would you still have a need to figure out the fling velocity on end?
sa...@squareup.com <sa...@squareup.com> #12
If transformable
can support nested scrolling, that'd be the best!
sa...@squareup.com <sa...@squareup.com> #13
Modifier.transformable() consumes all events by default even if its content can't pan any further, preventing scrollable parents from showing overscroll effects
Am I understanding it correctly that
sa...@squareup.com <sa...@squareup.com> #14
On a second thought, the new canPan
parameter isn't sufficient. It needs to also provide the pan delta so that consumers can decide if content can be panned in the gesture direction.
lp...@google.com <lp...@google.com>
ma...@google.com <ma...@google.com> #15
Main usecase we covered with this API is the ability to disable pan based on some external state (e.g. cumulative scale or rotataion or something else). It is not clear why you would want to decide on wether to pan or not based on the direction of the pan delta.
I understand your usecase, but this API is not intended to substitute nested scroll-like abilities
sa...@saket.me <sa...@saket.me> #16
If my content in a pager is zoomed in, but is also panned to the edge, is there a better way to return false from canPan
? The documentation of canPan
recommends using scale > 1f
but that may not be something that all apps use.
While I understand that this is leaking into nested scrolling, nested scrolling can't be used for 2d scrolling yet.
ma...@google.com <ma...@google.com> #17
Hmm, I see. The thing is that I don't think it will be possible to control the consumption of the events once you started the panning, e.g. if you are at the bound of the zoomed picture and the pointer goes down - providing delta will cover this case, but not when you reach the bound with the finger already down.
The only real way to make this change correctly is the nested scroll dispatch.
sa...@saket.me <sa...@saket.me> #18
e.g. if you are at the bound of the zoomed picture and the pointer goes down - providing delta will cover this case, but not when you reach the bound with the finger already down.
That sounds perfectly fine! Can I ask you to try out this experience using telephoto's sample on your phone?
ma...@google.com <ma...@google.com> #19
I see what you mean, that does make sense from the UX perspective. I see that in general it can be beneficial to have this info anyway, I will add Offset to canPan to help with that.
sa...@squareup.com <sa...@squareup.com> #20
Yay thank you!
ap...@google.com <ap...@google.com> #21
Branch: androidx-main
commit 6bcc8c148ecd1cb13f48ea2fab0582731f44daf6
Author: malkov <malkov@google.com>
Date: Fri May 19 15:37:10 2023
Add pan change Offset to canPan parameter in transformable to help make informed decision on pan start.
Since the addition of canPan parameter in transformable, it made sense to add pan delta to this callback to help making informated decisions, e.g. when zoomed image is panned to the bound it is important to understand the direction of the pan. Providing pan delta helps to deternime this.
Relnote: Modifier.transformable now provides pan delta in canPan parameter to help determine the direction of the pan to allow or disallow it.
Test: added new
Fixes: 266829800
Change-Id: I692aa5bf43084658ca6a20175869d9d593986f2b
M compose/foundation/foundation/api/current.txt
M compose/foundation/foundation/api/restricted_current.txt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TransformableTest.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Transformable.kt
sa...@squareup.com <sa...@squareup.com> #22
Hey folks, can this issue be reopened again?
ma...@google.com <ma...@google.com> #23
My bad, reopening and reassigning to the tracking hotlist to address in the future work
Description
I'm investigating if
Modifier#transformable()
can be used for a photo viewer screen. When a gesture ends, I'd like to reset the transformations if needed. For example, if the content is zoomed below< 1f
, it'll be scaled back1f
.I'm currently doing this by adding another
pointerInput(Unit)
modifier aftertransformable()
:Do you think this looks good enough? Or should
transformable()
offer start & end hooks if it offers any benefit?