Skip to content

Add support for scrolling a scroll view with a custom duration #1334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

skevy
Copy link
Contributor

@skevy skevy commented May 19, 2015

Adds scrollWithCustomDurationTo() to ScrollView.js.

I found that this was necessary when moving a scroll view to accommodate a keyboard -- rather than using the default animation duration, I wanted to animate the scroll view in 250ms to match the duration of the keyboard animation.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 19, 2015
@skevy skevy force-pushed the scroll-view-custom-duration branch 2 times, most recently from 67e4b5f to 9d3691c Compare May 19, 2015 03:09
@skevy skevy force-pushed the scroll-view-custom-duration branch from da0e9ee to b86af79 Compare May 19, 2015 03:46
@skevy
Copy link
Contributor Author

skevy commented May 19, 2015

FYI I refactored scrollTo and also allowed for custom easing. @ide @vjeux

@vjeux
Copy link
Contributor

vjeux commented May 19, 2015

Maybe we could make scroll position a controlled value and do (sneak peak of the animation API i'm working on)

getInitialState: function() {
  return { scrollY: new Animated.Value(0) };
}
onWhatever: function() {
  this.state.scrollY.animateTiming(150, {duration: 500, easing: Easing.quad});
}
render() {
  return <Animated.ScrollView scrollY={this.state.scrollY} />
}

Because Animated.Value is opaque, we don't even need to make it truly controlled. We can just serialize the animation and send it to native when it happens.

@ide what do you think? cc @sahrens

@ide
Copy link
Contributor

ide commented May 19, 2015

@vjeux: what is the behavior of the scroll view after the animation is finished? Does it stay pinned to y=150, or does a finished animation stop controlling the scroll position?

@vjeux
Copy link
Contributor

vjeux commented May 19, 2015

It would not stay pinned. But you are right this is super weird

One other thing we can do is

scrollY(y, animation)

Where animation can be TimingAnimation, DecayAnimation, SpringAnimation (currently implemented but we can use any), pre-compute the key frames and send them to native to actually do the interpolation. Would that work?

This way, we don't have to implement yet another way to describe those easing functions

@skevy
Copy link
Contributor Author

skevy commented May 19, 2015

@vjeux does the TimingAnimation, DecayAnimation, etc. stuff already exist somewhere? I can't find it. Or is it in FB's repo

@vjeux
Copy link
Contributor

vjeux commented May 19, 2015

Not yet, i'm iterating on it inside of facebook codebase, don't want to trash people while working on the api

@ide
Copy link
Contributor

ide commented May 19, 2015

@vjeux scrollTo(y, x, animation) would be a good stepping stone and preserve backward compatibility. The prop-driven API is interesting to me as an experiment though I'm not sure if it will work well in practice (I'm not against it - just don't know). Fine-grained control over the scroll position and content insets is so important for many apps.


other thoughts:

It's pretty interesting to have the scroll position not stay pinned. This notion of an "ephemeral value" could be used to replace imperative APIs and perhaps remove refs from React. To generalize, this code:

render() {
  return <X ref="x" />;
}
onEvent() {
  this.refs.x.performAction();
}

is now:

getInitialState() {
  return { performAction: new Animated.Boolean(false) };
}
render() {
  return <X performAction={this.state.performAction} />;
}
onEvent() {
  this.state.performAction.setEphemeralValue(true);  // true for one pass
}

This may also be the answer to making components like TextInput much more usable. Currently the asynchrony between JS and UIKit is janky and controlled TextInputs aren't usable in production. But I think there's a third type of TextInput -- semi-controlled -- where you generally don't need it to be controlled but occasionally want to set its value to a given string from JS, just like how the scroll view's position generally should not be controlled but sometimes we want to set the position from JS.

@skevy
Copy link
Contributor Author

skevy commented May 19, 2015

I agree that the prop driven API is interesting...but obviously in order to really make it viable, I think it would need to become idiomatic React...as right now, idiomatic React (at least, the public facing version) seems to be using refs to perform events on components.

I think @ide hits the nail on the head when he relates this API to making other components more usable and less imperative. I think there's a lot of power in that idea, and would be curious to see it explored further.

That being said...I think that keeping the scrollTo function and expanding on it is a good first step. I would love to add the animation stuff and agree it's better than passing in some weird options object...but I guess we'll just need to wait for what you come up with, @vjeux.

Should we keep this open just to remind us that it's here? Or should I close and revisit the refactor once the animation API you're talking about lands?

@vjeux
Copy link
Contributor

vjeux commented May 20, 2015

@ide your idea of semi-controlled components is fascinating! I have to sleep on it :) I'm sure @sahrens will enjoy it as well.

@skevy How urgent is it for you? I plan to have my api open sourced in the next few weeks. I'd love to revisit this once it is in a more advanced state. Would you mind keeping a fork for a while until things has settled?

@skevy
Copy link
Contributor Author

skevy commented May 20, 2015

It's urgent, but I don't mind keeping the fork.

Thanks for the feedback, and I look forward to seeing the new API!

@sahrens
Copy link
Contributor

sahrens commented May 20, 2015

The current TextInput is already basically semi-controlled because fully-controlled is janky due to async as you mention. If you don't update the value prop in js, the native value won't be overwritten, and if you continuously update the value, there is some buffering to try and reduce the jankiness by not overwriting the native value immediately.

Would be nice to have a better solution, perhaps a mechanism to provide a js code snippet to run synchronously on the main thread?

On May 19, 2015, at 8:15 PM, Adam Miskiewicz notifications@github.com wrote:

It's urgent, but I don't mind keeping the fork.

Thanks for the feedback, and I look forward to seeing the new API!


Reply to this email directly or view it on GitHub.

@a2 a2 assigned vjeux May 22, 2015
@vjeux
Copy link
Contributor

vjeux commented May 22, 2015

Okay, I'll close the pull request for now and will open it back when Animated is released. Thanks for bringing this up!

@vjeux vjeux closed this May 22, 2015
@maxs15
Copy link

maxs15 commented Aug 25, 2015

@vjeux maybe it's time to open back this issue ?

@aleclarson
Copy link
Contributor

perhaps a mechanism to provide a js code snippet to run synchronously on the main thread?

Is this something that could viably alleviate some performance issues? What difficulties are there in implementing such a thing?

Maybe we could make scroll position a controlled value

This idea is very interesting. Are there any inherent problems with making a scrollY an Animated.Value?

@ide
Copy link
Contributor

ide commented Feb 27, 2016

With the natively implemented Animated + gestures, this might actually make sense to do.

As for the original issue of specifying a custom duration, the scrollTo API now takes an object {x, y, animated} and could easily take a duration option without much API clutter.

@alpamys-qanybet
Copy link

@ide, can you please share code of scroll with duration for iOS. This pull request #1334 seems to be not working.

@sahrens
Copy link
Contributor

sahrens commented Jan 19, 2018

If someone wants to rebase and rework this with the simpler scrollTo({x, y, animated, duration, easing}) API, feel free to send a PR. Or if you want to make it possible to drive ScrollView::contentOffset with an Animated.Value and useNativeDriver, that would be even cooler. (Or both :P)

@sahrens
Copy link
Contributor

sahrens commented Jan 19, 2018

Oh nevermind, stuff is happening in #17422

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants