Erratic behavior when animating/setting padding in GestureImageView
See original GitHub issueI was trying to come up with a way to vertically offset the image inside a GestureImageView
when I noticed an erratic pattern that is not consistent.
Initially I tried to play with .setViewPort()
, but that only controls the size of the image, not the position. Then I checked padding and it works, to a certain degree.
If I set the padding manually in the xml layout file the image is exactly positioned as I expect it to be, but because there is UI that overlaps the view and that UI can be toggled with sliding animation I tried to animate the padding as well.
The top and left padding animations work perfectly, but for some reason the bottom and right do not work the same way, it feels like they are being completely ignored.
This video shows a basic example of what I am describing, please ignore the jerkiness/jumps because those are due to the fullscreen entering/exiting and are irrelevant to this example.
The top and left padding animation are working as expected, however the right and bottom padding values are not. Worse, they seem to be “taken into account” when the values are set back to normal.
This feels like the viewport position is being correctly updated, but the resizing/scale of it is not.
To replicate this problem replace the following code in this location: https://github.com/alexvasilkov/GestureViews/blob/master/sample/src/main/java/com/alexvasilkov/gestures/sample/demo/adapter/PhotoPagerAdapter.java#L66-L78
With this
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup container) {
final ViewHolder holder = new ViewHolder(container);
holder.image.setOnClickListener(view -> {
onImageClick();
// here we are simply animating all paddings of the view at the same
// time to 200px or 0px depending on if there is a padding already set
boolean show = holder.image.getPaddingTop() == 0;
ValueAnimator.AnimatorUpdateListener updateListener2 = animation -> {
holder.image.setPadding(
(int) animation.getAnimatedValue(),
(int) animation.getAnimatedValue(),
(int) animation.getAnimatedValue(),
(int) animation.getAnimatedValue()
);
};
ValueAnimator valueAnimator = ObjectAnimator.ofInt(show ? 0 : 200, show ? 200 : 0);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(updateListener2);
valueAnimator.start();
// end of code modification, everything else is the original untouched code
});
settingsController.apply(holder.image);
holder.image.getController().enableScrollInViewPager(viewPager);
holder.image.getPositionAnimator().addPositionUpdateListener((position, isLeaving) ->
holder.progress.setVisibility(position == 1f ? View.VISIBLE : View.INVISIBLE));
return holder;
}
Can we get this fixed somehow?
Note: I tried to play with changing the UI heights/real positions (not translations, but actual view repositioning) with the GestureView
constrained between them, but this interferes with the gesture behavior since the height adjustments are interpreted as gestures as well if the user is touching the view during the UI transitions. I also tried to just leave the view constrained with no views changing dimensions, but when the enter/leave animation is automatically clipped at the edges of the view (as if the view limits were the device screen limits).
The only working solution that has almost worked is to play with the padding and I cannot think of anything else to try.
Issue Analytics
- State:
- Created 3 years ago
- Comments:9 (2 by maintainers)
I’ll close this now since the issue has been resolved and it wasn’t technically an issue with the library itself as much as it was not the proper way to do this. Now that I understood your explanation I was able to resolve my predicament and I thank you for it.
In my head I was so far off from understanding something so simple. Yes, following your example it works right away, but the same issue as my hack persists: any zoom is lost between those changes - which you had already noted before - and that is where I got stuck previously.
After this I went about it this way:
.getState().getCopy()
.getState().set(float...)
.getController().updateState()
Now the zoom is not lost because it is being restored in between viewport changes, same for rotation and translation.
Here is the full code in case it is useful for anyone else in the future: