Skip to Content

Weekly issues of interest »
« MyPOD re-write, vector graphics improvements & DroidCon
submit to reddit

While making the flyout menu for the new MyPOD I encountered a little bug that I couldn’t find an answer for.

The problem ..

I was using offsetLeftAndRight to hold the flyout “open” after the animation finishes (simply using fillAfter on the animation produces and annoying flicker). This method takes a "relative" amount to move (i.e. the amount to offset the view from it’s current position). So this container hold whatever content might be in the front screen. But the problem was that whenever a child in this container called requestLayout. the offset would be wiped, and so the flyout would appear to suddenly close.

The API >10 solution

HoneyComb added the onLayoutChangeListener which makes it really easy to restore the old value, it is just provided in the method call.

if (Build.VERSION.SDK_INT>10) {
			_contentContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
				
				@Override
				public void onLayoutChange(View v, int left, int top, int right,
						int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
					_contentContainer.offsetLeftAndRight(oldLeft);
				}
			});
		}

And for the rest … API<=10

Without the layout change listener the only way I could think of to react to layout changes was to use tried and true override of the onLayout method. So the container class (RelativeLayout) was extended. This sets the accumulated value when the reset condition is detected (left==0 && left != _accumOffset). There may still be problems for other use cases, but for me it has the desired effect of preserving the open state of the flyout on all API Levels.

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

public class RelativeLayoutPreserveOffset extends RelativeLayout {
	int _accumOffset=0;
	
	public RelativeLayoutPreserveOffset(Context context, AttributeSet attrs,	int defStyle) {
		super(context, attrs, defStyle);
	}

	public RelativeLayoutPreserveOffset(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public RelativeLayoutPreserveOffset(Context context) {
		super(context);
	}

	@Override
	public void offsetLeftAndRight(int offset) {
		_accumOffset+=offset;
		super.offsetLeftAndRight(offset);
	}

	@Override
	protected void onLayout(boolean changed, int left, int t, int r, int b) {
		if (left != _accumOffset) {
			if ( left == 0 ) {
				super.offsetLeftAndRight(_accumOffset);
				super.onLayout(changed, _accumOffset, t, r, b);
			} else {
				_accumOffset=left;
				super.onLayout(changed, left, t, r, b);
			}
		} else {
			super.onLayout(changed, left, t, r, b);
		}
		
	}
}


One comment

  1. Thanks for presenting the solution that is Gingerbread compatible. A great help

    Comment by Randolf on June 20, 2013 at 9:37 am


Allowed HTML tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*

By submitting a comment you grant Sentinel Web Technologies a perpetual license to reproduce your words and name/web site in attribution. Inappropriate and irrelevant comments will be removed at an admin’s discretion. Your email is used for verification purposes only, it will never be shared.

Weekly issues of interest »
« MyPOD re-write, vector graphics improvements & DroidCon