content: package com.bihe0832.android.lib.ui.bottom.bar;
  
  import android.content.Context;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.util.AttributeSet;
  import android.view.Gravity;
  import android.view.ViewGroup;
  import android.view.ViewTreeObserver;
  import android.view.animation.AccelerateDecelerateInterpolator;
  import android.view.animation.Interpolator;
  import android.widget.LinearLayout;
  
  import androidx.core.view.ViewCompat;
  
  import java.util.ArrayList;
  import java.util.List;
  
  
  public class BottomBar extends LinearLayout {
      private static final int TRANSLATE_DURATION_MILLIS = 200;
  
      private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
      private boolean mVisible = true;
  
      private List<BaseBottomBarTab> mTabs = new ArrayList<>();
  
      private LinearLayout mTabLayout;
  
      private LayoutParams mTabParams;
      private int mCurrentPosition = 0;
      private int mDefaultPosition = 0;
  
      private OnTabSelectedListener mListener;
  
      public BottomBar(Context context) {
          this(context, null);
      }
  
      public BottomBar(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public BottomBar(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          init(context, attrs);
      }
  
      private void init(Context context, AttributeSet attrs) {
          setOrientation(VERTICAL);
          mTabLayout = new LinearLayout(context);
          mTabLayout.setOrientation(LinearLayout.HORIZONTAL);
          mTabLayout.setGravity(Gravity.BOTTOM);
          mTabLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
          addView(mTabLayout, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
          mTabParams = new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
          mTabParams.weight = 1;
      }
  
      public BottomBar addItem(final BaseBottomBarTab tab) {
          tab.getTabView().setOnClickListener(v -> {
              if (mListener == null) return;
  
              int pos = tab.getTabPosition();
              if (mCurrentPosition == pos) {
                  mListener.onTabReselected(pos);
              } else {
                  mListener.onTabSelected(pos, mCurrentPosition);
                  tab.setSelected(true);
                  mListener.onTabUnselected(mCurrentPosition);
                  mTabs.get(mCurrentPosition).setSelected(false);
                  mCurrentPosition = pos;
              }
          });
          tab.setTabPosition(mTabLayout.getChildCount());
          if (tab.getTabPosition() == mDefaultPosition) {
              mCurrentPosition = mDefaultPosition;
              tab.setSelected(true);
          } else {
              tab.setSelected(false);
          }
          tab.getTabView().setLayoutParams(mTabParams);
          mTabLayout.addView(tab.getTabView());
  
          mTabs.add(tab);
          return this;
      }
  
      public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
          mListener = onTabSelectedListener;
      }
  
      public void setCurrentItem(final int position) {
          mTabLayout.post(() -> mTabLayout.getChildAt(position).performClick());
      }
  
      public int getCurrentItemPosition() {
          return mCurrentPosition;
      }
  
      public void setDefaultPosition(int postion) {
          mDefaultPosition = postion;
      }
  
      /**
       * 获取 Tab
       */
      public BaseBottomBarTab getItem(int index) {
          if (mTabs.size() < index) return null;
          return mTabs.get(index);
      }
  
      public interface OnTabSelectedListener {
          void onTabSelected(int position, int prePosition);
  
          void onTabUnselected(int position);
  
          void onTabReselected(int position);
      }
  
      @Override
      protected Parcelable onSaveInstanceState() {
          Parcelable superState = super.onSaveInstanceState();
          return new SavedState(superState, mCurrentPosition);
      }
  
      @Override
      protected void onRestoreInstanceState(Parcelable state) {
          SavedState ss = (SavedState) state;
          super.onRestoreInstanceState(ss.getSuperState());
  
          if (mCurrentPosition != ss.position) {
              mTabLayout.getChildAt(mCurrentPosition).setSelected(false);
              mTabLayout.getChildAt(ss.position).setSelected(true);
          }
          mCurrentPosition = ss.position;
      }
  
      static class SavedState extends BaseSavedState {
          private int position;
  
          public SavedState(Parcel source) {
              super(source);
              position = source.readInt();
          }
  
          public SavedState(Parcelable superState, int position) {
              super(superState);
              this.position = position;
          }
  
          @Override
          public void writeToParcel(Parcel out, int flags) {
              super.writeToParcel(out, flags);
              out.writeInt(position);
          }
  
          public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
              public SavedState createFromParcel(Parcel in) {
                  return new SavedState(in);
              }
  
              public SavedState[] newArray(int size) {
                  return new SavedState[size];
              }
          };
      }
  
  
      public void hide() {
          hide(true);
      }
  
      public void show() {
          show(true);
      }
  
      public void hide(boolean anim) {
          toggle(false, anim, false);
      }
  
      public void show(boolean anim) {
          toggle(true, anim, false);
      }
  
      public boolean isVisible() {
          return mVisible;
      }
  
      private void toggle(final boolean visible, final boolean animate, boolean force) {
          if (mVisible != visible || force) {
              mVisible = visible;
              int height = getHeight();
              if (height == 0 && !force) {
                  ViewTreeObserver vto = getViewTreeObserver();
                  if (vto.isAlive()) {
                      // view树完成测量并且分配空间而绘制过程还没有开始的时候播放动画。
                      vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                          @Override
                          public boolean onPreDraw() {
                              ViewTreeObserver currentVto = getViewTreeObserver();
                              if (currentVto.isAlive()) {
                                  currentVto.removeOnPreDrawListener(this);
                              }
                              toggle(visible, animate, true);
                              return true;
                          }
                      });
                      return;
                  }
              }
              int translationY = visible ? 0 : height;
              if (animate) {
                  animate().setInterpolator(mInterpolator)
                          .setDuration(TRANSLATE_DURATION_MILLIS)
                          .translationY(translationY);
              } else {
                  ViewCompat.setTranslationY(this, translationY);
              }
          }
      }
  }
  