web-dev-qa-db-fra.com

Barre d'outils Android + Disposition des onglets + Tiroir, Masquer la barre d'outils lors du défilement et placer TabLayout en haut

J'ai une activité à laquelle un tiroir est attaché. Chaque menu du tiroir est un fragment et sous l'un des menus, j'ai un fragment avec TabLayout et chaque onglet contient un RecyclerView. Alors maintenant, lorsque je fais défiler la RecyclerView, la disposition des onglets devient masquée mais ToolBar reste en haut. Ce qu'il me faut, c'est ToolBar pour être caché (scrollFlags:scroll|enterAlways), et TabLayout devrait apparaître en haut.

La configuration actuelle est donc:

Activity with attached DrawerLayout -> Fragment with TabLayout -> Tab Fragment 1 with RecyclerView -> Tab Fragment 2 with RecyclerView

25
Vishal Pawale

Moins de code plus efficace

Bonjour @Vishal, j'ai trouvé trop pour vous. parce que je cherche aussi ce sujet avant quelque temps.

J'ai trouvé une bibliothèque brillante nommée MaterialViewPager qui est entièrement personnalisée avec ce que vous voulez masquer en mode défilement.

Voir la vidéo sur https://www.youtube.com/watch?v=r95Tt6AS18c

 enter image description here

13
Vishal Patel

Pouvez-vous utiliser la bibliothèque de conception de support? Il a ce comportement intégré pour faire exactement ce que vous avez décrit. Il utilise CoordinatorLayout pour accomplir cela.

<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:animateLayoutChanges="true"
    >
    <Android.support.design.widget.AppBarLayout
        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.TabLayout
            Android:id="@+id/tabanim_tabs"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content" />
    </Android.support.design.widget.AppBarLayout>
    <Android.support.v4.view.ViewPager
        Android:id="@+id/tabanim_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:src="@drawable/ic_alarm_add_white_48dp"
        app:layout_anchor="@id/tabanim_viewpager"
        app:layout_anchorGravity="bottom|right|end"
        Android:layout_margin="16dp"
        />

</Android.support.design.widget.CoordinatorLayout>
8
Tyler Pfaff

Vous devez d’abord implémenter un écouteur de défilement. Ici vous pouvez trouver un exemple HidingScrollListener. 

public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {

    private static final float HIDE_THRESHOLD = 10;
    private static final float SHOW_THRESHOLD = 70;

    private int mToolbarOffset = 0;
    private boolean mControlsVisible = true;
    private int mToolbarHeight;
    private int mTotalScrolledDistance;
    private int previousTotal = 0;
    private boolean loading = true;
    private int visibleThreshold = 4;
    int firstVisibleItem, visibleItemCount, totalItemCount;
    private LinearLayoutManager layoutManager;

    public HidingScrollListener(Context context, LinearLayoutManager layoutManager) {
        mToolbarHeight = Tools.getToolbarHeight(context);
        this.layoutManager = layoutManager;
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            if (mTotalScrolledDistance < mToolbarHeight) {
                setVisible();
            } else {
                if (mControlsVisible) {
                    if (mToolbarOffset > HIDE_THRESHOLD) {
                        setInvisible();
                    } else {
                        setVisible();
                    }
                } else {
                    if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                        setVisible();
                    } else {
                        setInvisible();
                    }
                }
            }
        }

    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        clipToolbarOffset();
        onMoved(mToolbarOffset);

        if ((mToolbarOffset < mToolbarHeight && dy > 0) || (mToolbarOffset > 0 && dy < 0)) {
            mToolbarOffset += dy;
        }
        if (mTotalScrolledDistance < 0) {
            mTotalScrolledDistance = 0;
        } else {
            mTotalScrolledDistance += dy;
        }
        // for load more
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = layoutManager.getItemCount();
        firstVisibleItem = layoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached
            // Do something

            loading = true;
            onLoadMore();
        }
    }

    private void clipToolbarOffset() {
        if (mToolbarOffset > mToolbarHeight) {
            mToolbarOffset = mToolbarHeight;
        } else if (mToolbarOffset < 0) {
            mToolbarOffset = 0;
        }
    }

    private void setVisible() {
        if (mToolbarOffset > 0) {
            onShow();
            mToolbarOffset = 0;
        }
        mControlsVisible = true;
    }

    private void setInvisible() {
        if (mToolbarOffset < mToolbarHeight) {
            onHide();
            mToolbarOffset = mToolbarHeight;
        }
        mControlsVisible = false;
    }

    public abstract void onMoved(int distance);

    public abstract void onShow();

    public abstract void onHide();

    public abstract void onLoadMore();
}

Ensuite, vous devez modifier votre adaptateur RecyclerView. Vous devez ajouter une vue vide en haut de votre RecyclerView aussi haut que votre votre Tolbar.

Voici un exemple de mise en page pour votre vue vide.

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/abc_action_bar_default_height_material" />

Vous devez ensuite redéfinir les méthodes getItemViewType et getITemCount de votre adaptateur, comme ci-dessous.

@Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position)) {
            return TYPE_HEADER;
        }
        return TYPE_ITEM;
    }

    private boolean isPositionHeader(int position) {
        return position == 0;
    }

    @Override
    public int getItemCount() {
        return mObjects.size() + 1;
    }

Dans la méthode onCreateViewHolder de l'adaptateur, renvoyez une présentation appropriée pour la position de votre RecyclerView, comme ci-dessous:

 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = null;
        switch (viewType) {
            case TYPE_HEADER:
                view = LayoutInflater.from(mContext).inflate(R.layout.layout_recycler_header, parent, false);
                return new RecyclerHeaderViewHolder(view);

            default:
                view = LayoutInflater.from(mContext).inflate(R.layout.row_recyclerview_category, parent, false);
                return new ViewHolder(view);
        }

    }

Et enfin, ajoutez votre implémentation HidingScrollListener à votre RecyclerView comme ci-dessous:

final int mToolbarHeight = Tools.getToolbarHeight(getActivity());
        RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mRecyclerView.setAdapter(mAdapter);
        mViewPager.setPadding(mRecyclerView.getPaddingLeft(),
                mToolbarHeight,
                mRecyclerView.getPaddingRight(),
                mRecyclerView.getPaddingBottom());

        mHidingScrollListener = new HidingScrollListener(getActivity(), linearLayoutManager) {
            @Override
            public void onMoved(int distance) {
              mToolbarContainer.setTranslationY(-distance);
            }

            @Override
            public void onShow() {
                mToolbarContainer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
            }

            @Override
            public void onHide() {
               mToolbarContainer.animate()
                        .translationY(-mToolbarHeight)
                        .setInterpolator(new AccelerateInterpolator(2))
                        .start();
            }

            @Override
            public void onLoadMore() {
            }
        };
        mRecyclerView.setOnScrollListener(mHidingScrollListener);

J'espère que je comprends votre problème correctement, et ma mise en œuvre peut vous aider. 

Bonne chance.

Éditer: Vous pouvez implémenter LoadMore et PullToRefresh facilement à cette solution. Vous pouvez ajouter votre demande d’API à loadMore . Il y a une partie tricy dans PullToRefresh . Après avoir actualisé, nettoyez vos données et avertissez l'adaptateur de ne pas oublier de définir set visibleItemCount et totalItemCount sur 0 dans votre implémentation de défilement masqué. Si vous ne définissez pas la valeur sur 0, votre charge ne fonctionnera plus correctement après l'actualisation. Vous obtiendrez moins de données car votre article compte dans votre pagination.

6
savepopulation

Vous pouvez essayer le suivant, que j’ai utilisé pour masquer la barre d’outils, et faire en sorte que le scrollview occupe tout l’écran pour une lecture complète de la page dans la conception de mon application.

C'est comme suit.

  1. Cacher la barre d'outils. 
  2. Obtenez la largeur et la hauteur de l'écran de votre téléphone.
  3. Stockez la disposition des tabulations Height et width dans une variable temporaire.
  4. Attribuez la largeur et la hauteur de l'écran du téléphone à la disposition de vos onglets.

Cela peut être fait de la manière suivante:

getSupportActionBar().hide();    
int mwidth = getApplicationContext().getResources().getDisplayMetrics().widthPixels;
int mheight = getApplicationContext().getResources().getDisplayMetrics().heightPixels;
temp = (TabLayout) myfrag.getActivity().findViewById(R.id.TabLayout_genesis);
int getwidth = temp.getWidth();
int getheight = temp.getHeight();
temp.setMinimumHeight(mheight);
temp.setMinimumWidth(mwidth);

J'espère que ça aide. 

2
HourGlass

J'avais la même architecture dans mon application, voici comment je le fais:

<Android.support.design.widget.CoordinatorLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/coordinator"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
xmlns:app="http://schemas.Android.com/apk/res-auto"
>

<Android.support.design.widget.AppBarLayout
    Android:id="@+id/appbar_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/main_toolbar"
    Android:layout_width="match_parent"
    Android:layout_height="?attr/actionBarSize"
    Android:background="@color/chat_primary_color"
    app:layout_scrollFlags="scroll|enterAlways"
    Android:elevation="4dp"/>

<Android.support.design.widget.TabLayout
    Android:id="@+id/tab_layout"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="?attr/colorPrimary"
    Android:elevation="6dp"
    Android:minHeight="?attr/actionBarSize"
    Android:layout_below="@id/main_toolbar"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
</Android.support.design.widget.AppBarLayout>

<Android.support.v4.view.ViewPager
    Android:id="@+id/pager"
    Android:layout_width="match_parent"
    Android:layout_height="fill_parent"
    Android:layout_below="@id/appbar_layout"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    />
<Android.support.v4.widget.NestedScrollView
    Android:id="@+id/container_fragment"
    Android:layout_width="match_parent"
    Android:layout_height="fill_parent"
    Android:layout_below="@id/appbar_layout"
    Android:fillViewport="true"
    Android:foregroundGravity="center"
    app:layout_behavior=".FixedScrollingViewBehavior"
    />

Le ViewPager utilisé pour les onglets et le NestedScrollView utilisé comme FrameLayout pour l'autre fragment, je montre le ViewPager pour les fragments nécessitant des onglets et je masque le NestedScrollView dans l'autre cas.

Vous pouvez trouver le comportement ici pour le NestedScrollView FixedScrollingViewBehavior

2
Context

Vous pouvez nous montrer votre code xml si vous voulez trouver vos bogues. Le Ci-dessous est mon partage de code pour ceux qui veulent implémenter Toolbar, Drawer, Tab et RecycleView dans leur application.

https://github.com/Gujarats/Android-Toolbar-Drawer-tab-recyvleview-

J'espère que ça aide

2
Gujarat Santana

Autant que je sache, rien n’est prévu pour vous. Cependant, vous pouvez consulter le code source Google IO, en particulier BaseActivity. Recherchez "auto hide" ou consultez onMainContentScrolled

Afin de cacher la barre d’outils, vous pouvez faire quelque chose comme ceci:

toolbar.animate().translationY(-toolbar.getBottom()).setInterpolator(new AccelerateInterpolator()).start();

Si vous voulez le montrer à nouveau, vous appelez:

toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator()).start();

Trouvé ici: Barre d'outils Android Lollipop: comment masquer/afficher la barre d'outils lors du défilement?

1
Will Evers
Everyone is giving the code, "Talk is cheap, show me the code" right. 
I prefer not showing the code this time. 
I will talk. I do not recommand such a complicated activity.

DrawerLayout et TabLayout sont les deux principales méthodes de navigation pour Android. DrawerLayout et TabLayout présentés dans une même activité s’opposent à la ligne de développement Android. Et si vous le faites, votre application sera très difficile à utiliser. 

Imaginez que, si l'utilisateur fait un balayage droit-gauche, devez-vous faire glisser le geste de la vue d'ensemble ou du dessin du tiroir? Je vois que vous pouvez appliquer le geste de balayage à la vue du tiroir lorsque l'utilisateur balaie du côté droit de l'activité, sinon vous pouvez appliquer le geste à la vue d'ensemble, mais comment vous assurer que l'utilisateur connaît cette règle? 

Même les utilisateurs savent comment balayer votre activité (les utilisateurs peuvent très bien avoir un sens de nos jours), votre application a toujours l’air très compliquée.

Ma suggestion est, 

 if you have less than 5 main menus, just use tablayout + actionbar, 
 if you have more than 5 main menus, use drawerlayout + actionbar. 
 you don't have to use both navigation in a row, you can still place the important actions to the actionbar right.
1
Daniel Martin Shum

Pour masquer votre barre d’outils à tout moment, vous pouvez utiliser:

getSupportActionBar().hide();

pour plus d'explications voir url1 ou url2

0
Karan Khurana

Supprimer la mise en page du coordinateur utilisée dans l’activité à onglets. Utiliser LinearLayout

0
droid1233