package carbon.widget; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.v7.view.menu.MenuBuilder; import android.util.AttributeSet; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; import carbon.CarbonContextWrapper; import carbon.R; import carbon.drawable.DefaultColorStateList; public class BottomBar extends FrameLayout { private LinearLayout content; private Menu menu; private View activeView; MenuItem.OnMenuItemClickListener listener; public BottomBar(Context context) { super(context); inflate(context, R.layout.carbon_bottombar, this); content = (LinearLayout) findViewById(R.id.carbon_bottomBarContent); } public BottomBar(Context context, AttributeSet attrs) { super(context, attrs); inflate(context, R.layout.carbon_bottombar, this); content = (LinearLayout) findViewById(R.id.carbon_bottomBarContent); setOnClickListener(v -> Log.e("dasd", "dsad")); } public BottomBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); inflate(context, R.layout.carbon_bottombar, this); content = (LinearLayout) findViewById(R.id.carbon_bottomBarContent); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public BottomBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); inflate(context, R.layout.carbon_bottombar, this); content = (LinearLayout) findViewById(R.id.carbon_bottomBarContent); } public void setMenu(int resId) { Menu menu = new MenuBuilder(new CarbonContextWrapper(getContext())); MenuInflater inflater = new MenuInflater(getContext()); inflater.inflate(resId, menu); setMenu(menu); } public void setMenu(Menu menu) { this.menu = menu; content.removeAllViews(); content.setWeightSum(menu.size()); for (int i = 0; i < menu.size(); i++) { final MenuItem item = menu.getItem(i); final View view = View.inflate(getContext(), R.layout.carbon_bottombar_item, null); view.setOnClickListener(v -> { if (view == activeView) return; if (activeView != null) { deselectItem(activeView); } selectItem(view); if (listener != null) listener.onMenuItemClick(item); }); ImageView icon = (ImageView) view.findViewById(R.id.carbon_bottomIcon); icon.setTint(new DefaultColorStateList(getContext())); icon.setImageDrawable(item.getIcon()); TextView text = (TextView) view.findViewById(R.id.carbon_bottomText); text.setTextColor(new DefaultColorStateList(getContext())); text.setText(item.getTitle()); content.addView(view, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1)); } } private void selectItem(final View item) { activeView = item; final ImageView icon = (ImageView) item.findViewById(R.id.carbon_bottomIcon); icon.setSelected(true); final TextView text = (TextView) item.findViewById(R.id.carbon_bottomText); text.setSelected(true); ValueAnimator animator = ValueAnimator.ofFloat(1, getResources().getDimension(R.dimen.carbon_bottomBarActiveTextSize) / getResources().getDimension(R.dimen.carbon_bottomBarInactiveTextSize)); animator.setDuration(200); animator.setInterpolator(new DecelerateInterpolator()); animator.addUpdateListener(animation -> { text.setScaleX((Float) animation.getAnimatedValue()); text.setScaleY((Float) animation.getAnimatedValue()); text.postInvalidate(); }); animator.start(); ValueAnimator animator2 = ValueAnimator.ofFloat(0, -getResources().getDimension(R.dimen.carbon_1dip) * 2); animator2.setDuration(200); animator2.setInterpolator(new DecelerateInterpolator()); animator2.addUpdateListener(animation -> { icon.setTranslationY((Float) animation.getAnimatedValue()); icon.postInvalidate(); }); animator2.start(); } private void deselectItem(final View item) { final ImageView icon = (ImageView) item.findViewById(R.id.carbon_bottomIcon); icon.setSelected(false); final TextView text = (TextView) item.findViewById(R.id.carbon_bottomText); text.setSelected(false); ValueAnimator animator = ValueAnimator.ofFloat(getResources().getDimension(R.dimen.carbon_bottomBarActiveTextSize) / getResources().getDimension(R.dimen.carbon_bottomBarInactiveTextSize), 1); animator.setDuration(200); animator.setInterpolator(new DecelerateInterpolator()); animator.addUpdateListener(animation -> { text.setScaleX((Float) animation.getAnimatedValue()); text.setScaleY((Float) animation.getAnimatedValue()); text.postInvalidate(); }); animator.start(); ValueAnimator animator2 = ValueAnimator.ofFloat(-getResources().getDimension(R.dimen.carbon_1dip) * 2, 0); animator2.setDuration(200); animator2.setInterpolator(new DecelerateInterpolator()); animator2.addUpdateListener(animation -> { icon.setTranslationY((Float) animation.getAnimatedValue()); icon.postInvalidate(); }); animator2.start(); } public int getSelectedIndex() { if (activeView == null) return -1; return content.indexOfChild(activeView); } public void setSelectedIndex(int index) { if (activeView != null) deselectItem(activeView); selectItem(content.getChildAt(index)); } public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) { this.listener = listener; } @Override public Parcelable onSaveInstanceState() { //begin boilerplate code that allows parent classes to save state Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); //end ss.selectedIndex = getSelectedIndex(); return ss; } @Override public void onRestoreInstanceState(Parcelable state) { //begin boilerplate code so parent classes can restore state if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); //end this.setSelectedIndex(ss.selectedIndex); } static class SavedState implements Parcelable { public static final SavedState EMPTY_STATE = new SavedState() { }; int selectedIndex; Parcelable superState; SavedState() { superState = null; } SavedState(Parcelable superState) { this.superState = superState != EMPTY_STATE ? superState : null; } private SavedState(Parcel in) { Parcelable superState = in.readParcelable(BottomBar.class.getClassLoader()); this.superState = superState != null ? superState : EMPTY_STATE; this.selectedIndex = in.readInt(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel out, int flags) { out.writeParcelable(superState, flags); out.writeInt(this.selectedIndex); } public Parcelable getSuperState() { return superState; } //required field that makes Parcelables from a Parcel public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }