/**
* A {@link FrameLayout} that can show different states one at a time.
*/
public class StateFrameLayout extends ViewAnimator {
public static final String STATE_LOADING = "loading";
public static final String STATE_EMPTY = "empty";
public static final String STATE_ERROR = "error";
private static final String STATE_DEFAULT = "default";
private SimpleArrayMap<String, View> stateViewMap;
public StateFrameLayout(Context context) {
super(context);
init();
}
public StateFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* Shows the given state and hides the current state.
*/
public void showState(String state) {
View view = stateViewMap.get(state);
if (view.getVisibility() == View.VISIBLE) {
return;
}
setDisplayedChild(indexOfChild(view));
}
/**
* Alias for {@link #showState(String)} with STATE_DEFAULT as the parameter.
*/
public void reset() {
showState(STATE_DEFAULT);
}
/**
* Registers the given View as the content view for this layout. By default,
* this layout will select its first child as the content view. This method
* will override that behavior.
*/
public void setContentView(View view) {
stateViewMap.put(STATE_DEFAULT, view);
}
/**
* Assigns the given View to the given State and adds the View to the view
* hierarchy.
*/
public void setState(String state, View view) {
// If state already exists, it means a view already exists for this
// state. Therefore, we need to remove that existing view from the view
// hierarchy.
if (stateViewMap.containsKey(state)) {
View existingView = stateViewMap.get(state);
removeView(existingView);
}
stateViewMap.put(state, view);
view.setVisibility(View.GONE);
addView(view);
}
/**
* Returns the view associated with the given state
*/
public View getViewForState(String state) {
return stateViewMap.get(state);
}
@Override protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getChildCount() > 0) {
setContentView(getChildAt(0));
}
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stateViewMap.clear();
}
private void init() {
stateViewMap = new SimpleArrayMap<>();
Animation in = new AlphaAnimation(0, 1);
in.setDuration(150);
setInAnimation(in);
Animation out = new AlphaAnimation(1, 0);
out.setDuration(150);
setOutAnimation(out);
// Ensure that this FrameLayout only measures child views that are View.VISIBLE or View.INVISIBLE.
setMeasureAllChildren(false);
}
}