web-dev-qa-db-fra.com

Comment implémenter la barre d'outils repliable personnalisée dans Android?

Utilisation de ce tutoriel pour implémenter un modèle d'espace flexible (celui avec la barre d'outils de réduction).

J'essaie d'obtenir un effet similaire à celui de l'activité Lollipop Contacts , qui au début lors de la saisie de l'activité, les vues ne sont qu'une partie de l'image entête:

enter image description here

Ensuite, l'utilisateur peut faire défiler la mise en page sous l'image afin d'en révéler plus, jusqu'à ce qu'elle atteigne le maximum:

enter image description here

Dans mon application, je n'arrive pas à le faire fonctionner.

Ce qui se passe, c'est que lors de la saisie de l'activité, l'en-tête de l'image est présenté à sa taille maximale , la taille de l'AppBarLayout, tout comme la mise en page ci-dessus, et contrairement à l'activité Lollipop Contacts , où il ne montre qu'une partie de l'image.

C'est le code qui définit la hauteur de l'AppBarLayout (je veux que la largeur de l'écran soit la hauteur maximale):

int widthPx = getResources().getDisplayMetrics().widthPixels;
AppBarLayout appbar = (AppBarLayout)findViewById(R.id.appbar);
appbar.setLayoutParams(new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, widthPx));

Et c'est le code qui définit le RecyclerView. Essayé en utilisant scrollToPosition, pensait que cela soulèverait la vue de RecyclerView, mais cela n'a aucun effet:

mRecyclerView = (RecyclerView) findViewById(R.id.activity_profile_bottom_recyclerview);

    mRecyclerView.setHasFixedSize(true);

    // use a linear layout manager
    mLayoutManager = new LinearLayoutManager(this);

    mRecyclerView.setLayoutManager(mLayoutManager);

    // specify an adapter (see also next example)
    if(mAdapter == null){
        mAdapter = new ProfileAdapter(this, user, inEditMode);
        mRecyclerView.setAdapter(mAdapter);
    }

    mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1); // itemCount is 4

Voici la mise en page xml:

<Android.support.v4.widget.DrawerLayout 
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/activity_profile"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true">

<Android.support.design.widget.CoordinatorLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true">
    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/appbar"
        Android:layout_width="match_parent"
        Android:layout_height="0dp" // set programatically
        Android:fitsSystemWindows="true"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
        <Android.support.design.widget.CollapsingToolbarLayout
            Android:id="@+id/collapsing_toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginBottom="32dp"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <ImageView
                Android:id="@+id/header"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:background="@drawable/header"
                Android:fitsSystemWindows="true"
                Android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />
            <Android.support.v7.widget.Toolbar
                Android:id="@+id/anim_toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        </Android.support.design.widget.CollapsingToolbarLayout>
    </Android.support.design.widget.AppBarLayout>

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/activity_profile_bottom_recyclerview"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 

    </Android.support.design.widget.CoordinatorLayout>

    <include layout="@layout/navigation_view"/>
</Android.support.v4.widget.DrawerLayout>

Remarque: Si je défile manuellement vers le bas, le RecyclerView descend et révèle plus de l'image, cela ne fonctionnera tout simplement pas avec le code.

Je pense que scrollToPosition n'est pas la solution, quelqu'un a-t-il une idée?

Pensé à utiliser le drapeau enterAlwaysCollapsed peut-être comme mentionné ici dans la section CoordinatorLayout et Appbar avec minHeight:

enterAlwaysCollapsed: lorsque votre vue a déclaré un minHeight et que vous utilisez cet indicateur, votre vue n'entrera qu'à sa hauteur minimale (c.-à-d., "repliée"), ne se ré-agrandissant à sa hauteur maximale que lorsque la vue de défilement a atteint son sommet.

J'ai donc défini l'indicateur scroll | enterAlwaysCollapsed sur ma barre d'outils et minHeight dans mon RecyclerView, ce qui n'a pas fonctionné. Ensuite, j'ai essayé de déplacer le minHeight vers d'autres mises en page telles que AppBarLayout, rien n'a fonctionné. Il a juste rétréci l'image parfois sans la vue entière.

82
Jjang

AppBarComponent fournit une méthode appelée .setExpanded(boolean expanded), qui vous permet de développer votre AppBarComponent.

Mais gardez à l'esprit que cette méthode repose sur le fait que cette disposition est un enfant direct d'un CoordinatorLayout.

Vous pouvez lire this pour plus d'informations.

Si vous souhaitez animer avec un décalage personnalisé, essayez d'utiliser la méthode setTopAndBottomOffset(int).

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt();
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
            appBar.requestLayout();
        }
    });
    valueAnimator.setIntValues(0, -900);
    valueAnimator.setDuration(400);
    valueAnimator.start();
}
1
Lukas