Skip to content

Commit

Permalink
Don't show gap in SlidingRelativeLayout (Fix #841) (#881)
Browse files Browse the repository at this point in the history
* Don't show gap in SlidingRelativeLayout (Fix #841)

* minor improvemenents / bugfixes

- add getters (again)
- fix: check if view tree observer is alive before adding/removing listener to avoid possible crash
- fix: calling both setXFraction and setYFraction before view is measured did not correctly set the former onPreDraw
  • Loading branch information
ENT8R authored and westnordost committed Feb 20, 2018
1 parent c50ba44 commit 2f2e7de
Showing 1 changed file with 36 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
});
}
}
}
}

0 comments on commit 2f2e7de

Please sign in to comment.