diff --git a/app/src/main/java/de/westnordost/streetcomplete/view/SlidingRelativeLayout.java b/app/src/main/java/de/westnordost/streetcomplete/view/SlidingRelativeLayout.java index f6cd1f01ab..c88f48e18f 100644 --- a/app/src/main/java/de/westnordost/streetcomplete/view/SlidingRelativeLayout.java +++ b/app/src/main/java/de/westnordost/streetcomplete/view/SlidingRelativeLayout.java @@ -2,11 +2,14 @@ import android.content.Context; import android.util.AttributeSet; -import android.view.View; +import android.view.ViewTreeObserver; import android.widget.RelativeLayout; public class SlidingRelativeLayout extends RelativeLayout { + private float yFraction; + private float xFraction; + public SlidingRelativeLayout(Context context) { super(context); @@ -24,36 +27,49 @@ public SlidingRelativeLayout(Context context, AttributeSet attrs, int defStyleAt public void setYFraction(float fraction) { - /* Here we have to tackle two problems: - - the layout may not be measured yet. If it isn't hidden, this will result in an ugly - flicker in the first frame of the animation - - users can turn animations off (i.e. battery saver mode), which results in that all - animations "start" in their final frame immediately. If the view is hidden in the first - frame, it will never appear - solution: hide it only if it was not measured yet AND it should be translated */ - setVisibility(getHeight() == 0 && fraction != 0 ? View.INVISIBLE : View.VISIBLE); - - float translationY = getHeight() * fraction; - setTranslationY(translationY); + this.yFraction = fraction; + postAfterViewMeasured(() -> setTranslationY(getHeight() * yFraction)); } public float getYFraction() { - if(getHeight() == 0) return 0; - return getTranslationY() / getHeight(); + return yFraction; } public void setXFraction(float fraction) { - setVisibility(getWidth() == 0 && fraction != 0 ? View.INVISIBLE : View.VISIBLE); - - float translationX = getWidth() * fraction; - setTranslationX(translationX); + this.xFraction = fraction; + postAfterViewMeasured(() -> setTranslationX(getWidth() * xFraction)); } public float getXFraction() { - if(getWidth() == 0) return 0; - return getTranslationX() / getWidth(); + return xFraction; + } + + private void postAfterViewMeasured(Runnable runnable) + { + if (getWidth() != 0 || getHeight() != 0) + { + runnable.run(); + } + else + { + if(getViewTreeObserver().isAlive()) + { + getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() + { + @Override public boolean onPreDraw() + { + runnable.run(); + if(getViewTreeObserver().isAlive()) + { + getViewTreeObserver().removeOnPreDrawListener(this); + } + return true; + } + }); + } + } } }