Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Nkzn/b40a294fa50db8369f169140d0c12878 to your computer and use it in GitHub Desktop.
Save Nkzn/b40a294fa50db8369f169140d0c12878 to your computer and use it in GitHub Desktop.
Saving and restoring BottomNavigationView state (No Shadow settings)
import android.content.Context;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.NavigationView;
import android.support.v4.os.ParcelableCompat;
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
import android.support.v7.view.menu.MenuItemImpl;
import android.support.v7.view.menu.MenuView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import static android.support.design.widget.TabLayout.Tab.INVALID_POSITION;
public class StateBottomNavigationView extends BottomNavigationView {
private ViewGroup mBottomItemsHolder;
private int mLastSelection = INVALID_POSITION;
public StateBottomNavigationView(Context context) {
super(context);
}
public StateBottomNavigationView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StateBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public int getSelectedItem() {
return mLastSelection = findSelectedItem();
}
@CallSuper
public void setSelectedItem(int position) {
if (position >= getMenu().size() || position < 0) return;
View menuItemView = getMenuItemView(position);
if (menuItemView == null) return;
MenuItemImpl itemData = ((MenuView.ItemView) menuItemView).getItemData();
itemData.setChecked(true);
boolean previousHapticFeedbackEnabled = menuItemView.isHapticFeedbackEnabled();
menuItemView.setSoundEffectsEnabled(false);
menuItemView.setHapticFeedbackEnabled(false); //avoid hearing click sounds, disable haptic and restore settings later of that view
menuItemView.performClick();
menuItemView.setHapticFeedbackEnabled(previousHapticFeedbackEnabled);
menuItemView.setSoundEffectsEnabled(true);
mLastSelection = position;
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
BottomNavigationState state = new BottomNavigationState(superState);
mLastSelection = getSelectedItem();
state.lastSelection = mLastSelection;
return state;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof BottomNavigationState)) {
super.onRestoreInstanceState(state);
return;
}
BottomNavigationState bottomNavigationState = (BottomNavigationState) state;
mLastSelection = bottomNavigationState.lastSelection;
dispatchRestoredState();
super.onRestoreInstanceState(bottomNavigationState.getSuperState());
}
private void dispatchRestoredState() {
if (mLastSelection != 0) { //Since the first item is always selected by the default implementation, dont waste time
setSelectedItem(mLastSelection);
}
}
private View getMenuItemView(int position) {
View bottomItem = mBottomItemsHolder.getChildAt(position);
if (bottomItem instanceof MenuView.ItemView) {
return bottomItem;
}
return null;
}
private int findSelectedItem() {
int itemCount = getMenu().size();
for (int i = 0; i < itemCount; i++) {
View bottomItem = mBottomItemsHolder.getChildAt(i);
if (bottomItem instanceof MenuView.ItemView) {
MenuItemImpl itemData = ((MenuView.ItemView) bottomItem).getItemData();
if (itemData.isChecked()) return i;
}
}
return INVALID_POSITION;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mBottomItemsHolder = (ViewGroup) getChildAt(0);
}
static class BottomNavigationState extends BaseSavedState {
public int lastSelection;
@RequiresApi(api = Build.VERSION_CODES.N)
public BottomNavigationState(Parcel in, ClassLoader loader) {
super(in, loader);
lastSelection = in.readInt();
}
public BottomNavigationState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(lastSelection);
}
public static final Parcelable.Creator<NavigationView.SavedState> CREATOR
= ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<NavigationView.SavedState>() {
@Override
public NavigationView.SavedState createFromParcel(Parcel parcel, ClassLoader loader) {
return new NavigationView.SavedState(parcel, loader);
}
@Override
public NavigationView.SavedState[] newArray(int size) {
return new NavigationView.SavedState[size];
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment