2016-10-20 33 views
5

staram się osiągnąć coś takiego https://material.google.com/components/bottom-navigation.html#bottom-navigation-behaviorAndroid Pomoc Projekt: BottomNavigationView

Ale zdaniem recyklingiem ukrywa się poniżej paska narzędzi i brak efektu jest BottomNavigationView

Poniżej jest mój kod

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(); 
      } 

     } 
+0

Próbowałem uruchomiony kod, wszystko działa bez zarzutu. Co masz na myśli przez "brak wpływu na BottomNavigationView"? Masz na myśli efekt przewijania, taki jak pasek narzędzi? – Srijith

+0

tak i zauważ, że pierwszy element RecyclerView jest poniżej paska narzędzi. – sector11

+0

Myślę, że zachowanie przewijania nie jest jeszcze dostępne dla BottomNavigationView. Możesz jednak zaimplementować niestandardowe zachowanie. Jeśli chodzi o recyclerview pierwszy element, zobacz moją odpowiedź – Srijith

Odpowiedz

15

Edit: Oto prosty przykład pokazujący jak zaimplementować przewijanie zachowanie ruchowe https://github.com/sjthn/BottomNavigationViewBehavior

zmienić XML do tego:

<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> 
+0

Dziękuję koleś, i zawiedli całkowicie z layout_ anchor/gravity. – sector11

+0

Masz rację I przewijam 'RecyclerView' jego Hide' ActionBar' ale nie ukrywam 'BottomNavigatioView', jego tam jest chory. –

+0

Czy layout_anchor i layout_anchorGravity są przeznaczone do użycia w ten sposób? Widziałem ich tylko w połączeniu z FAB –

1

więc z niewielką pomocą @Srijith jestem w stanie animować sposób, w jaki jest podany w linku.

Częścią tej odpowiedzi jest

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); 
    } 

} 

Wszystko to odpowiedź przyszła z tym facetem: https://medium.com/@nullthemall/bottom-navigation-behavior-388b9b206667#.potyetdkb

cały projekt znajduje here