¿Cómo implementar la barra de herramientas plegable personalizada en Android?

80

Usando este tutorial para implementar un patrón de espacio flexible (el que tiene la barra de herramientas colapsada).

Estoy tratando de lograr un efecto similar al de la actividad Contactos de Lollipop , que al principio, al ingresar a la actividad, las vistas son solo una parte del encabezado de la imagen:

ingrese la descripción de la imagen aquí

Luego, el usuario puede desplazarse hacia abajo en el diseño debajo de la imagen para revelar más, hasta que alcance el máximo:

ingrese la descripción de la imagen aquí

En mi aplicación, no puedo hacer que funcione.

Lo que sucede es que al ingresar a la actividad, el encabezado de la imagen se presenta en su tamaño máximo, el tamaño del AppBarLayout, tal como el diseño anterior, y a diferencia de la actividad Contactos de Lollipop , donde solo muestra una parte de la imagen.

Este es el código que establece la altura de AppBarLayout (quiero que el ancho de la pantalla sea la altura máxima):

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

Y este es el código que establece el RecyclerView. Intenté usar scrollToPosition, pensé que elevaría la vista de RecyclerView, pero no tiene ningún efecto:

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

Este es el diseño 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>

Nota: Si me desplazo hacia abajo manualmente, RecyclerView baja y revela más de la imagen, simplemente no funcionará a través del código.

Creo que scrollToPosition no es la solución, ¿alguien tiene alguna idea?

Pensé en usar la bandera enterAlwaysCollapsed tal vez como se menciona aquí en la sección CoordinatorLayout y Appbar con minHeight:

enterAlwaysCollapsed: cuando su vista ha declarado un minHeight y usa esta bandera, su Vista solo ingresará a su altura mínima (es decir, 'colapsada'), solo se volverá a expandir a su altura completa cuando la vista de desplazamiento haya alcanzado su parte superior.

Entonces, configuré la bandera scroll | enterAlwaysCollapsed en mi barra de herramientas y minHeight en mi RecyclerView, que no funcionó. Luego intenté mover minHeight a otros diseños como AppBarLayout, nada funcionó. Simplemente encogió la imagen a veces sin la vista completa.

Jjang
fuente
2
Gracias @karaokyo, esto realmente funcionó. Todavía estoy tratando de averiguar si también hay otras soluciones.
Jjang
@karaokyo, ¿podrías ver esto por favor? stackoverflow.com/questions/33069081/…
Jjang
Usaría MotionLayout para hacer estas cosas. Vea ejemplos en https://github.com/android/views-widgets-samples/tree/master/ConstraintLayoutExamples
Lin Lin

Respuestas:

1

El AppBarComponentproporciona un método llamado .setExpanded(boolean expanded), que le permite expandir su AppBarComponent.

Pero tenga en cuenta que este método se basa en que este diseño es un hijo directo de un CoordinatorLayout.

Puede leer esto para obtener más información.

Si desea animar a un desplazamiento personalizado, intente usar el setTopAndBottomOffset(int)método.

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