Last active
December 25, 2017 23:19
-
-
Save alexfu/685c3215e3f8b296aea7905d523f41b4 to your computer and use it in GitHub Desktop.
A FrameLayout that can show different states one at a time.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment