androidx / constraintlayout

ConstraintLayout is an Android layout component which allows you to position and size widgets in a flexible way
Apache License 2.0
1.07k stars 176 forks source link

MotionLayout Custom custom property bug #627

Closed jafu888 closed 2 years ago

jafu888 commented 2 years ago

The custom property bug is due to different lifecycle it seems The calls are captured before the layout

example -- proper interpolation of 1/ custom colors (top/bottom colors of the gradient) 2/ some float value, used to compute final color and thus distinguish between "current item" vs others (the current item has value of 1, rest have nothing so 0). So no need to have a notion of progress or who's the main item, just have the option to pass the motionproperties and use them.

https://user-images.githubusercontent.com/15019413/173118367-db978754-77cd-4069-bafd-9668a98a044a.mov

camaelon commented 2 years ago

Current tip of tree showing the broken behavior (notice that while the custom interpolators are behaving incorrectly, the overall layout is indeed correct)

https://user-images.githubusercontent.com/23424811/173119478-9ba68043-c9b2-4b7c-b757-d81f45dfe9fb.mov

camaelon commented 2 years ago

The issue is that the custom interpolators are not using the current progress value, because we set the progress value via the layout pass in MultiMeasureLayout -- yet, those interpolators are called before ...

Possible fix (YMMV) :

1/ add a motionCustomProgress in MotionMeasurer (in addition to motionProgress) 2/ in MotionMeasurer.getCustomColor() and MotionMeasurer.getCustomFloat() use motionCustomProgress instead of motinoProgress 3/ add a setMotionCustomProgress setter to MotionMeasurer... 4/ in MotionLayoutCore invocation, call measurer.setMotionCustomProgress(progress) before calling MultiMeasureLayout() (eg l. 434)

This way, the progress value used by the getCustomColor/getCustomFloat will be up to date, otherwise those calls are captured before the MultiMeasureLayout pass and have the previous value.

oscar-ad commented 2 years ago

I think it might work by just calculating the custom properties with the motionProgress value at recomposition. I think the custom properties should work more like a stateless class that gets updated during composition with the progress value and transition to interpolate.

oscar-ad commented 2 years ago

Here, Before it's with current behavior, notice how I drag the box to the start and end but the progress value (a custom property) shows a different number other than 0 or 100. Background color is also a custom property but of course the effect is not as clear.

After calculates the customProperty with the progress value at recomposition, note how when I drag the box to start and end, the value shows 0 and 100 respectively. The custom properties are now properly synchronized with the measured layout in composition.

PR coming soon, fixing custom properties will eventually cause breaking API changes. customPropBefore.webm customPropAfter.webm