12

I am currenlty exploring a somewhat complex UI similar to the BottomSheetBehaviour used in Google Maps, where one can animate an item from a collapsed state into an expanded state. The transition between those 2 states are Scene Transitions using the TransitionManager framework and work rather nicely.

I am now exploring a way to drag the expanded view again into the collapsed state and vice versa, but I did not find any obvious way to manually progress a scene transition.

What I would need would be something like: Transition.setAnimatedFraction(0.5f) based on the percentage the user has dragged between the 2 states.

A drag transition between those 2 states

Does anyone here have any idea on how to achieve that?

saberrider
  • 585
  • 3
  • 16
  • Hello @saberrider, Have you found out how to implement this? It would be great if you share your implementation. – Amin Mousavi Jun 07 '18 at 21:43
  • Hi @AminMousavi I have not found a nice and clean way to do it. The only way i achieved a very simple version of what i wanted to do, was to obtain Transition.getRunningAnimators() through reflection, stop all of them, and then set the animated time manually. It causes a lot of issues in various places and is definitely not production ready. To solve this properly would basically require to reengineer the TransitionManager and all the Transition classes respectively. – saberrider Jun 08 '18 at 08:46
  • Here's an idea to try - create a custom TimeInterpolator that returns the 0..1 value based on the touch location. set the scene transition to use it. – Amir Uval Aug 21 '18 at 13:18
  • @auval I went down that path during my explorations. The issue is that no matter what timeinterpolator you come up with, the animation finishes after a given amount of time. therefore the transition will set the finished states on all objects after that time. You might suggest to just set time to something close to infinity, but that then leaves you with the situation that the TransitionManager.runningAnimators() are in a limbo state. and in order to restore order you will need again to use reflection to manually finish all of them. – saberrider Aug 22 '18 at 11:45
  • In the Animator class there are pause(), resume() and setDuration(). If you set a non-interactive duration of 300ms for example, then during the touch gesture from srcY to dstY you make sure to increase the duration (for example we went 50% of the way) - to 450ms, set the interpolator according to normalized srcY and dstY, resume, and pause when reaching dstY. repeat on next drag point. – Amir Uval Aug 22 '18 at 12:05
  • That is exactly what i ended up doing and I described a couple of comments above. The problem is that without reflection you won't get to all involved animators unless you fork the whole transitionManager framework. – saberrider Aug 22 '18 at 12:52
  • A while ago while one could make suggestions for the Android P grey/ blacklisted APIs I filed a feature request for google just for that topic: https://issuetracker.google.com/issues/110314356 – saberrider Aug 22 '18 at 12:58

1 Answers1

4

Migrating your parent ViewGroup (whatever is ConstraintLayout, RelativeLayout or anything else) to MotionLayout you can achieve this using MotionLayout.progress (setProgress(float)) and loadLayoutDescription which give you power to process manually progress of a scene transition described in a motion scene.

Please see examples here.

Arsenius
  • 4,972
  • 4
  • 26
  • 39