在Scroll上隐藏RecyclerView / ListView上的ActionBar
在我的应用程序中,我得到了顶部的某种操作栏和下面的列表视图。 我想要做的就是把它向上滚动到列表中,所以它隐藏起来,然后当列表向下滚动时,它应该向下滚动列表,就像它刚好在屏幕上边界一样。 我怎样才能实现这个function?
更新6/3/2015:
Google现在使用CoordinatorLayout
支持这一点。
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" 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:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_scrollFlags="scroll|enterAlways" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" android:src="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>
来源: https : //github.com/chrisbanes/cheesesquare/blob/master/app/src/main/res/layout/include_list_viewpager.xml
logging在这里: https : //developer.android.com/reference/android/support/design/widget/AppBarLayout.html
原始答案:
与Google Play音乐和Umano应用类似的示例:
https://github.com/umano/AndroidSlidingUpPanel
看看这个仓库中的代码。 当您滑动面板时,ActionBar也向上滑动。
从演示 :
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); SlidingUpPanelLayout layout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout); layout.setShadowDrawable(getResources().getDrawable(R.drawable.above_shadow)); layout.setAnchorPoint(0.3f); layout.setPanelSlideListener(new PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) { Log.i(TAG, "onPanelSlide, offset " + slideOffset); if (slideOffset < 0.2) { if (getActionBar().isShowing()) { getActionBar().hide(); } } else { if (!getActionBar().isShowing()) { getActionBar().show(); } } } @Override public void onPanelExpanded(View panel) { Log.i(TAG, "onPanelExpanded"); } @Override public void onPanelCollapsed(View panel) { Log.i(TAG, "onPanelCollapsed"); } @Override public void onPanelAnchored(View panel) { Log.i(TAG, "onPanelAnchored"); } });
下载示例:
https://play.google.com/store/apps/details?id=com.sothree.umano
ListView – 没有库:
我最近想要相同的function,这完全适合我:
随着用户向上滚动,ActionBar将被隐藏,以便为用户提供整个屏幕的工作。
当用户向下滚动并放开时,ActionBar将返回。
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getId() == listView.getId()) { final int currentFirstVisibleItem = listView.getFirstVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { // getSherlockActivity().getSupportActionBar().hide(); getSupportActionBar().hide(); } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { // getSherlockActivity().getSupportActionBar().show(); getSupportActionBar().show(); } mLastFirstVisibleItem = currentFirstVisibleItem; } } });
RecyclerView – 没有库
this.mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); final int currentFirstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition(); if (currentFirstVisibleItem > this.mLastFirstVisibleItem) { MainActivity.this.getSupportActionBar().hide(); } else if (currentFirstVisibleItem < this.mLastFirstVisibleItem) { MainActivity.this.getSupportActionBar().show(); } this.mLastFirstVisibleItem = currentFirstVisibleItem; } });
让我知道如果你需要更多的帮助!
由于通过隐藏/显示ActionBar的内容布局更改的可用空间,导致重新布局,因此您会遇到闪烁现象。 有了这个,第一个可见项的位置的索引也会改变(你可以通过注销mLastFirstVisibleItem和currentFirstVisibleItem来validation。
你可以通过让ActionBar覆盖你的内容布局来应对闪烁。 要为动作栏启用叠加模式,您需要创build一个自定义主题,以扩展现有的动作栏主题,并将android:windowActionBarOverlay属性设置为true 。
有了这个,你可以消除闪烁,但操作栏将覆盖您的列表视图的内容。 一个简单的解决scheme是将listview(或根布局的)顶部填充设置为操作栏的高度。
<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="?android:attr/actionBarSize" />
不幸的是,这将导致在顶部不断填充。 这个解决scheme的一个改进是添加一个标题视图到列表视图,该视图的高度是?android:attr / actionBarSize (并删除顶部的填充集)
你正在寻找的是所谓的快速返回模式 ,适用于操作栏。 Google IO 2014应用正是如此。 我在我的一个应用程序中使用它,你可以检查该应用程序的源代码 ,看看他们是如何得到它的。 BaseActivity类是你所需要的地方,阅读代码并提取特定的function。 享受编码! 🙂
我相信这不是最好的解决scheme。 但我还没有find更好的。 希望这将是有益的。
static boolean scroll_down; ... mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (scroll_down) { actionBar.hide(); } else { actionBar.show(); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 70) { //scroll down scroll_down = true; } else if (dy < -5) { //scroll up scroll_down = false; } } });
我有一个想法,这是一个好主意。
listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_FLING: if (view.getId()==lv_searchresult_results.getId()){ final int currentFirstVisibleItem=lv_searchresult_results.getFirstVisiblePosition(); if(currentFirstVisibleItem>mLastFirstVisibleItem){ ObjectAnimator.ofFloat(toolbar, "translationY", -toolbar.getHeight()).start(); else if(currentFirstVisibleItem<(mLastFirstVisibleItem)){ ObjectAnimator.ofFloat(toolbar, "translationY", 0).start(); } mLastFirstVisibleItem= currentFirstVisibleItem; } if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){ if(myAdapter.getListMap().size() < allRows&&!upLoading){ } } break; case OnScrollListener.SCROLL_STATE_IDLE: if (view.getFirstVisiblePosition()<=1){ ObjectAnimator.ofFloat(toolbar, "translationY", 0).start(); } if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){ if(myAdapter.getListMap().size() < allRows&&!upLoading){ } } break;
我认为它会正常工作…..
listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = listView.getLastVisiblePosition(); boolean isScrolling = false; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if(scrollState == 0) isScrolling = false; else if(scrollState == 1) isScrolling = true; else if(scrollState == 2) isScrolling = true; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getId() == myTeamListView.getId()) { if(isScrolling) { final int currentFirstVisibleItem = myTeamListView.getLastVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { ((AppCompatActivity)getActivity()).getSupportActionBar().hide(); } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { ((AppCompatActivity)getActivity()).getSupportActionBar().show(); } mLastFirstVisibleItem = currentFirstVisibleItem; } } } });
如果你正在使用CoordinatorLayout,这里有一个窍门。
<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:layout_scrollFlags="scroll|enterAlways"
行将导致我们的工具栏滚动屏幕,当用户向下滚动列表,一旦他开始向上滚动工具栏将再次出现。