В моем приложении у меня появилась активность с какой-то панелью действий вверху и списком ниже. То, что я хочу сделать, - это прокрутить его вверх со списком, чтобы он скрывался, а затем, когда список прокручивается вниз, он должен прокручиваться вниз со списком, как будто это было только над верхней границей экрана. как я могу достичь этой функциональности?
Скрытие ActionBar в RecyclerView/ListView onScroll
Ответ 1
Обновлено 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://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 - без библиотек:
Недавно мне нужна была такая же функциональность, и это отлично работает для меня:
По мере того, как пользователь прокручивается вверх, 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;
        }
    });
Сообщите мне, если вам нужна помощь!
Ответ 2
Вы испытываете мерцание, поскольку скрываете/показываете ActionBar доступное пространство для изменений макета контента, что вызывает ретрансляцию. При этом также изменяется индекс первой видимой позиции элемента (вы можете проверить это, выгрузив mLastFirstVisibleItem и currentFirstVisibleItem.
Вы можете справиться с мерцанием, позволяя ActionBar наложить макет содержимого. Чтобы включить режим наложения для панели действий, вам необходимо создать настраиваемую тему, которая расширяет существующую тему панели действий и устанавливает свойство android: windowActionBarOverlay как true.
С помощью этого вы можете устранить мерцание, но панель действий наложит ваше содержимое списка. Простое решение для этого - установить верхний отступ 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" />
К сожалению, это приведет к постоянному заполнению вверху. Уточнение этого решения заключается в том, чтобы добавить представление заголовка в представление списка, которое имеет высоту ? Android: attr/actionBarSize (и удалить ранее установленный верхний набор)
Ответ 3
То, что вы ищете, называется Образцом быстрого возврата, применяемым к панели действий. Google IO 2014 использует именно это. Я использую его в одном из моих приложений, вы можете проверить исходный код этого приложения Google, чтобы узнать, как он его получил. Класс BaseActivity - это то, где у вас есть то, что вам нужно, читайте код и извлекайте только эту конкретную функциональность. Наслаждайтесь кодированием!:)
Ответ 4
Я уверен, что это не лучшее решение. Но я еще не нашел лучшего. Надеюсь, это будет полезно.
    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;
            }
        }
    });
		Ответ 5
У меня есть мысль, что это хорошая идея.
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;
		Ответ 6
Я думаю, что все будет хорошо.
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;
                    }
                }
            }
        });
		Ответ 7
Если вы используете координаторLayout, вот трюк.
<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" заставит нашу панель инструментов прокручивать экран, когда пользователь прокручивает список вниз, и как только он начнет прокрутку, панель инструментов снова появится.