Android Support Design: BottomNavigationView

匿名 (未验证) 提交于 2019-12-03 03:00:02

问题:

I am trying to achieve something like this https://material.google.com/components/bottom-navigation.html#bottom-navigation-behavior

But recycler view is hiding below toolbar and no effect is on BottomNavigationView

Below is my code

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:id="@+id/activity_main"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:fitsSystemWindows="true"     tools:context=".MainActivity">      <android.support.design.widget.AppBarLayout         android:id="@+id/app_bar_layout"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">           <android.support.v7.widget.Toolbar             android:id="@+id/toolbar"             android:layout_width="match_parent"             android:layout_height="?attr/actionBarSize"             android:background="?attr/colorPrimary"             app:layout_scrollFlags="scroll|enterAlways"             app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />     </android.support.design.widget.AppBarLayout>       <RelativeLayout         android:layout_width="match_parent"         android:layout_height="match_parent">           <android.support.design.widget.BottomNavigationView             android:id="@+id/nm_bottom"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_alignParentBottom="true"             android:background="@color/colorPrimaryDark"             android:foregroundTint="@color/colorAccent"             app:itemIconTint="@android:color/white"             app:itemTextColor="@android:color/white"             app:menu="@menu/nav_menu" />          <android.support.v7.widget.RecyclerView             android:id="@+id/rv"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:layout_above="@id/nm_bottom"             app:layout_behavior="@string/appbar_scrolling_view_behavior" />     </RelativeLayout>  </android.support.design.widget.CoordinatorLayout> 

item.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="wrap_content"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:padding="4dp">      <android.support.v7.widget.CardView         android:layout_width="match_parent"         android:layout_height="wrap_content"         app:cardElevation="2dp">          <RelativeLayout             android:layout_width="fill_parent"             android:layout_height="?android:attr/listPreferredItemHeight"             android:padding="4dp">              <ImageView                 android:id="@+id/icon"                 android:layout_width="wrap_content"                 android:layout_height="fill_parent"                 android:layout_alignParentBottom="true"                 android:layout_alignParentTop="true"                 android:layout_marginRight="6dip"                 android:contentDescription="TODO"                 android:src="@drawable/ic_storage" />              <TextView                 android:id="@+id/secondLine"                 android:layout_width="fill_parent"                 android:layout_height="26dip"                 android:layout_alignParentBottom="true"                 android:layout_alignParentRight="true"                 android:layout_toRightOf="@id/icon"                 android:ellipsize="marquee"                 android:text="Description"                 android:textSize="12sp" />              <TextView                 android:id="@+id/firstLine"                 android:layout_width="fill_parent"                 android:layout_height="wrap_content"                 android:layout_above="@id/secondLine"                 android:layout_alignParentRight="true"                 android:layout_alignParentTop="true"                 android:layout_alignWithParentIfMissing="true"                 android:layout_toRightOf="@id/icon"                 android:gravity="center_vertical"                 android:text="Example application"                 android:textSize="16sp" />          </RelativeLayout>     </android.support.v7.widget.CardView> </FrameLayout>     public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {              private static final Logger logger = Logger.getLogger(MainActivity.class.getSimpleName());              private BottomNavigationView navigationView;             private RecyclerView mRecyclerView;             private MyAdapter mAdapter;              @Override             protected void onCreate(Bundle savedInstanceState) {                 super.onCreate(savedInstanceState);                 setContentView(R.layout.activity_main);                 initViews();             }              private void initViews() {                 navigationView = (BottomNavigationView) findViewById(R.id.nm_bottom);                 navigationView.setOnNavigationItemSelectedListener(this);                 mRecyclerView = (RecyclerView) findViewById(R.id.rv);                  // use this setting to improve performance if you know that changes                 // in content do not change the layout size of the RecyclerView                 mRecyclerView.setHasFixedSize(true);                  // use a linear layout manager                 LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);                 mRecyclerView.setLayoutManager(mLayoutManager);                  // specify an adapter (see also next example)                 List<String> myDataset = new ArrayList<>();                 for (int i = 0; i < 100; i++) {                     myDataset.add("Index #" + i);                 }                 mAdapter = new MyAdapter(myDataset);                 mRecyclerView.setAdapter(mAdapter);             }              @Override             public boolean onNavigationItemSelected(@NonNull MenuItem item) {                  return false;             }         }          public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {             private List<String> mDataset;              // Provide a reference to the views for each data item             // Complex data items may need more than one view per item, and             // you provide access to all the views for a data item in a view holder             public class ViewHolder extends RecyclerView.ViewHolder {                 // each data item is just a string in this case                 public TextView txtHeader;                 public TextView txtFooter;                  public ViewHolder(View v) {                     super(v);                     txtHeader = (TextView) v.findViewById(R.id.firstLine);                     txtFooter = (TextView) v.findViewById(R.id.secondLine);                 }             }              public void add(int position, String item) {                 mDataset.add(position, item);                 notifyItemInserted(position);             }              public void remove(String item) {                 int position = mDataset.indexOf(item);                 mDataset.remove(position);                 notifyItemRemoved(position);             }              // Provide a suitable constructor (depends on the kind of dataset)             public MyAdapter(List<String> myDataset) {                 mDataset = myDataset;             }              // Create new views (invoked by the layout manager)             @Override             public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,                                                            int viewType) {                 // create a new view                 View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_view, parent, false);                 // set the view's size, margins, paddings and layout parameters                 ViewHolder vh = new ViewHolder(v);                 return vh;             }              // Replace the contents of a view (invoked by the layout manager)             @Override             public void onBindViewHolder(ViewHolder holder, int position) {                 // - get element from your dataset at this position                 // - replace the contents of the view with that element                 final String name = mDataset.get(position);                 holder.txtHeader.setText(mDataset.get(position));                 holder.txtHeader.setOnClickListener(new View.OnClickListener() {                     @Override                     public void onClick(View v) {                         remove(name);                     }                 });                  holder.txtFooter.setText("Footer: " + mDataset.get(position));              }              // Return the size of your dataset (invoked by the layout manager)             @Override             public int getItemCount() {                 return mDataset.size();             }          } 

回答1:

Edit: Here is a simple sample showing how to implement scrolling behavior https://github.com/sjthn/BottomNavigationViewBehavior

Change your XML to this:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:id="@+id/activity_main"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:fitsSystemWindows="true"     tools:context=".MainActivity">      <android.support.design.widget.AppBarLayout         android:id="@+id/app_bar_layout"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">           <android.support.v7.widget.Toolbar             android:id="@+id/toolbar"             android:layout_width="match_parent"             android:layout_height="?attr/actionBarSize"             android:background="?attr/colorPrimary"             app:layout_scrollFlags="scroll|enterAlways"             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"             app:title="@string/app_name" />     </android.support.design.widget.AppBarLayout>      <android.support.v7.widget.RecyclerView         android:id="@+id/rv"         android:layout_width="match_parent"         android:layout_height="match_parent"         app:layout_behavior="@string/appbar_scrolling_view_behavior" />      <android.support.design.widget.BottomNavigationView         android:id="@+id/nm_bottom"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:background="@color/colorPrimaryDark"         android:foregroundTint="@color/colorAccent"         app:itemIconTint="@android:color/white"         app:itemTextColor="@android:color/white"         app:layout_anchor="@+id/rv"         app:layout_anchorGravity="bottom"         app:menu="@menu/nav_menu" />  </android.support.design.widget.CoordinatorLayout> 


回答2:

So with little help from @Srijith i am able to animate the way it is given in link.

Part of this answer is

public class BottomNavigationBehavior<V extends View> extends VerticalScrollingBehavior<V> {     private static final Interpolator INTERPOLATOR = new LinearOutSlowInInterpolator();     private int mBottomNavigationViewId;     private boolean hidden = false;     private ViewPropertyAnimatorCompat mTranslationAnimator;     private BottomNavigationView navigationView;     private View mTabsHolder;      public BottomNavigationBehavior() {         super();     }      public BottomNavigationBehavior(Context context, AttributeSet attrs) {         super(context, attrs);         mBottomNavigationViewId = R.id.nm_bottom;     }      @Override     public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {         boolean layoutChild = super.onLayoutChild(parent, child, layoutDirection);         if (navigationView == null && mBottomNavigationViewId != View.NO_ID) {             navigationView = findTabLayout(child);             getTabsHolder();         }         return layoutChild;     }      private BottomNavigationView findTabLayout(View child) {         return (BottomNavigationView) child.findViewById(mBottomNavigationViewId);     }      @Override     public void onNestedVerticalOverScroll(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int direction, int currentOverScroll, int totalOverScroll) {     }      @Override     public void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection) {         handleDirection(child, scrollDirection);     }      private void handleDirection(V child, int scrollDirection) {         if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_DOWN && hidden) {             hidden = false;             animateOffset(child, 0);         } else if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_UP && !hidden) {             hidden = true;             animateOffset(child, child.getHeight());         }     }      @Override     protected boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, @ScrollDirection int scrollDirection) {         handleDirection(child, scrollDirection);         return true;     }      private void animateOffset(final V child, final int offset) {         ensureOrCancelAnimator(child);         mTranslationAnimator.translationY(offset).start();         animateTabsHolder(offset);     }      private void animateTabsHolder(int offset) {         if (mTabsHolder != null) {             offset = offset > 0 ? 0 : 1;             ViewCompat.animate(mTabsHolder).alpha(offset).setDuration(200).start();         }     }       private void ensureOrCancelAnimator(V child) {         if (mTranslationAnimator == null) {             mTranslationAnimator = ViewCompat.animate(child);             mTranslationAnimator.setDuration(100);             mTranslationAnimator.setInterpolator(INTERPOLATOR);         } else {             mTranslationAnimator.cancel();         }     }      private void getTabsHolder() {         if (navigationView != null) {             mTabsHolder = navigationView.getChildAt(0);         }     }      public static <V extends View> BottomNavigationBehavior<V> from(V view) {         ViewGroup.LayoutParams params = view.getLayoutParams();         if (!(params instanceof CoordinatorLayout.LayoutParams)) {             throw new IllegalArgumentException("The view is not a child of CoordinatorLayout");         }         CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params)                 .getBehavior();         if (!(behavior instanceof BottomNavigationBehavior)) {             throw new IllegalArgumentException(                     "The view is not associated with ottomNavigationBehavior");         }         return (BottomNavigationBehavior<V>) behavior;     }      public void setTabLayoutId(@IdRes int tabId) {         this.mBottomNavigationViewId = tabId;     } }  public abstract class VerticalScrollingBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {      private int mTotalDyUnconsumed = 0;     private int mTotalDy = 0;     @ScrollDirection     private int mOverScrollDirection = ScrollDirection.SCROLL_NONE;     @ScrollDirection     private int mScrollDirection = ScrollDirection.SCROLL_NONE;      public VerticalScrollingBehavior(Context context, AttributeSet attrs) {         super(context, attrs);     }      public VerticalScrollingBehavior() {         super();     }      @Retention(RetentionPolicy.SOURCE)     @IntDef({ScrollDirection.SCROLL_DIRECTION_UP, ScrollDirection.SCROLL_DIRECTION_DOWN})     public @interface ScrollDirection {         int SCROLL_DIRECTION_UP = 1;         int SCROLL_DIRECTION_DOWN = -1;         int SCROLL_NONE = 0;     }       /*        @return Overscroll direction: SCROLL_DIRECTION_UP, CROLL_DIRECTION_DOWN, SCROLL_NONE    */     @ScrollDirection     public int getOverScrollDirection() {         return mOverScrollDirection;     }       /**      * @return Scroll direction: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN, SCROLL_NONE      */      @ScrollDirection     public int getScrollDirection() {         return mScrollDirection;     }       /**      * @param coordinatorLayout      * @param child      * @param direction         Direction of the overscroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN      * @param currentOverScroll Unconsumed value, negative or positive based on the direction;      * @param totalOverScroll   Cumulative value for current direction      */     public abstract void onNestedVerticalOverScroll(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int direction, int currentOverScroll, int totalOverScroll);      /**      * @param scrollDirection Direction of the overscroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN      */     public abstract void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection);      @Override     public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {         return (nestedScrollAxes & View.SCROLL_AXIS_VERTICAL) != 0;     }      @Override     public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {         super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);     }      @Override     public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {         super.onStopNestedScroll(coordinatorLayout, child, target);     }      @Override     public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {         super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);         if (dyUnconsumed > 0 && mTotalDyUnconsumed < 0) {             mTotalDyUnconsumed = 0;             mOverScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP;         } else if (dyUnconsumed < 0 && mTotalDyUnconsumed > 0) {             mTotalDyUnconsumed = 0;             mOverScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN;         }         mTotalDyUnconsumed += dyUnconsumed;         onNestedVerticalOverScroll(coordinatorLayout, child, mOverScrollDirection, dyConsumed, mTotalDyUnconsumed);     }      @Override     public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {         super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);         if (dy > 0 && mTotalDy < 0) {             mTotalDy = 0;             mScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP;         } else if (dy < 0 && mTotalDy > 0) {             mTotalDy = 0;             mScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN;         }         mTotalDy += dy;         onDirectionNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, mScrollDirection);     }       @Override     public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed) {         super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);         mScrollDirection = velocityY > 0 ? ScrollDirection.SCROLL_DIRECTION_UP : ScrollDirection.SCROLL_DIRECTION_DOWN;         return onNestedDirectionFling(coordinatorLayout, child, target, velocityX, velocityY, mScrollDirection);     }      protected abstract boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, @ScrollDirection int scrollDirection);      @Override     public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {         return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);     }      @Override     public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, V child, WindowInsetsCompat insets) {          return super.onApplyWindowInsets(coordinatorLayout, child, insets);     }      @Override     public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) {         return super.onSaveInstanceState(parent, child);     }  } 

All this answer came from this guy: https://medium.com/@nullthemall/bottom-navigation-behavior-388b9b206667#.potyetdkb

Entire Project is located here



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!