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);
}
}
}










