android - tutorial - CollapsingToolbarLayout con una vista personalizada
layout collapsemode parallax (3)
Estoy intentando implementar CollapsingToolbarLayout con una vista personalizada, pero no puedo hacerlo:
Lo que quiero hacer (lo siento, no puedo publicar imágenes, así que está en imgur):
Ampliado, el encabezado es una pantalla de perfil con imagen y título.
No expandido (en el desplazamiento), la imagen y el título estarán en la barra de herramientas
Pero todo lo que vi no funcionaba como esperaba.
Soy nuevo en esto y en las animaciones de piruletas, así que si alguien me puede ayudar, ¡estaré muy agradecido!
(No publico código de ejemplo porque no tengo algo relevante para publicar)
Puede usar este ejemplo de código https://github.com/saulmm/CoordinatorBehaviorExample de Saul MM para lograr este efecto. El código es demasiado grande para pegarlo aquí, por lo que no se pega ningún código. Espero que esto te ayude.
Puedes usar esta library , es muy flexible y tienes instrucciones en su página.
Mi solución
Tenía el mismo escenario que implementar, así que empecé con el ejemplo del perro e hice algunos cambios para que funcionara exactamente como lo describiste. Mi código se puede encontrar como una bifurcación en ese proyecto, consulte https://github.com/hanscappelle/CoordinatorBehaviorExample
Los cambios más importantes están en el diseño:
<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.support.design.widget.AppBarLayout
android:id="@+id/main.appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/main.collapsing"
android:layout_width="match_parent"
android:layout_height="@dimen/expanded_toolbar_height"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
>
<FrameLayout
android:id="@+id/main.framelayout.title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
>
<LinearLayout
android:id="@+id/main.linearlayout.title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/spacing_small"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="bottom|center_horizontal"
android:text="@string/tequila_name"
android:textColor="@android:color/white"
android:textSize="@dimen/textsize_xlarge"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/spacing_xxsmall"
android:text="@string/tequila_tagline"
android:textColor="@android:color/white"
/>
</LinearLayout>
</FrameLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="@dimen/spacing_xsmall"
android:padding="@dimen/spacing_normal"
android:text="@string/lorem"
android:textSize="@dimen/textsize_medium"
/>
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.Toolbar
android:id="@+id/main.toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
app:layout_anchor="@id/main.collapsing"
app:theme="@style/ThemeOverlay.AppCompat.Dark"
app:title=""
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<Space
android:layout_width="@dimen/image_final_width"
android:layout_height="@dimen/image_final_width"
/>
<TextView
android:id="@+id/main.textview.title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:gravity="center_vertical"
android:text="@string/tequila_title"
android:textColor="@android:color/white"
android:textSize="@dimen/textsize_large"
/>
</LinearLayout>
</android.support.v7.widget.Toolbar>
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="@dimen/image_width"
android:layout_height="@dimen/image_width"
android:layout_gravity="top|center_horizontal"
android:layout_marginTop="@dimen/spacing_normal"
android:src="@drawable/ninja"
app:border_color="@android:color/white"
app:border_width="@dimen/border_width"
app:finalHeight="@dimen/image_final_width"
app:finalXPosition="@dimen/spacing_small"
app:finalYPosition="@dimen/spacing_small"
app:finalToolbarHeight="?attr/actionBarSize"
app:layout_behavior="saulmm.myapplication.AvatarImageBehavior"
/>
</android.support.design.widget.CoordinatorLayout>
Y en la clase AvatarImageBehaviour que optimicé para mover solo el avatar desde la posición original a la posición configurada en los atributos. Entonces, si desea que la imagen se mueva desde otra ubicación, simplemente muévala dentro del diseño. Cuando lo hagas, asegúrate de que AppBarLayout aún sea un hermano o no se encuentre en el código.
package saulmm.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;
import de.hdodenhof.circleimageview.CircleImageView;
public class AvatarImageBehavior extends CoordinatorLayout.Behavior<CircleImageView> {
// calculated from given layout
private int startXPositionImage;
private int startYPositionImage;
private int startHeight;
private int startToolbarHeight;
private boolean initialised = false;
private float amountOfToolbarToMove;
private float amountOfImageToReduce;
private float amountToMoveXPosition;
private float amountToMoveYPosition;
// user configured params
private float finalToolbarHeight, finalXPosition, finalYPosition, finalHeight;
public AvatarImageBehavior(
final Context context,
final AttributeSet attrs) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AvatarImageBehavior);
finalXPosition = a.getDimension(R.styleable.AvatarImageBehavior_finalXPosition, 0);
finalYPosition = a.getDimension(R.styleable.AvatarImageBehavior_finalYPosition, 0);
finalHeight = a.getDimension(R.styleable.AvatarImageBehavior_finalHeight, 0);
finalToolbarHeight = a.getDimension(R.styleable.AvatarImageBehavior_finalToolbarHeight, 0);
a.recycle();
}
}
@Override
public boolean layoutDependsOn(
final CoordinatorLayout parent,
final CircleImageView child,
final View dependency) {
return dependency instanceof AppBarLayout; // change if you want another sibling to depend on
}
@Override
public boolean onDependentViewChanged(
final CoordinatorLayout parent,
final CircleImageView child,
final View dependency) {
// make child (avatar) change in relation to dependency (toolbar) in both size and position, init with properties from layout
initProperties(child, dependency);
// calculate progress of movement of dependency
float currentToolbarHeight = startToolbarHeight + dependency.getY(); // current expanded height of toolbar
// don''t go below configured min height for calculations (it does go passed the toolbar)
currentToolbarHeight = currentToolbarHeight < finalToolbarHeight ? finalToolbarHeight : currentToolbarHeight;
final float amountAlreadyMoved = startToolbarHeight - currentToolbarHeight;
final float progress = 100 * amountAlreadyMoved / amountOfToolbarToMove; // how much % of expand we reached
// update image size
final float heightToSubtract = progress * amountOfImageToReduce / 100;
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
lp.width = (int) (startHeight - heightToSubtract);
lp.height = (int) (startHeight - heightToSubtract);
child.setLayoutParams(lp);
// update image position
final float distanceXToSubtract = progress * amountToMoveXPosition / 100;
final float distanceYToSubtract = progress * amountToMoveYPosition / 100;
float newXPosition = startXPositionImage - distanceXToSubtract;
//newXPosition = newXPosition < endXPosition ? endXPosition : newXPosition; // don''t go passed end position
child.setX(newXPosition);
child.setY(startYPositionImage - distanceYToSubtract);
return true;
}
private void initProperties(
final CircleImageView child,
final View dependency) {
if (!initialised) {
// form initial layout
startHeight = child.getHeight();
startXPositionImage = (int) child.getX();
startYPositionImage = (int) child.getY();
startToolbarHeight = dependency.getHeight();
// some calculated fields
amountOfToolbarToMove = startToolbarHeight - finalToolbarHeight;
amountOfImageToReduce = startHeight - finalHeight;
amountToMoveXPosition = startXPositionImage - finalXPosition;
amountToMoveYPosition = startYPositionImage - finalYPosition;
initialised = true;
}
}
}
Fuentes
El ejemplo más común es el que tiene el perro en la lista en https://github.com/saulmm/CoordinatorBehaviorExample . Es un buen ejemplo, pero de hecho tiene la barra de herramientas en medio de la vista ampliada con una imagen de fondo que también se mueve. Todo lo que se eliminó en mi ejemplo.
Otra explicación se encuentra en http://www.devexchanges.info/2016/03/android-tip-custom-coordinatorlayout.html pero dado que la imagen de fondo de la nube / mar a la que se hace referencia también se encuentra en el ejemplo del perro, uno está claramente basado en encima de la otra.
También encontré esta pregunta SO con una recompensa otorgada, pero realmente no pude averiguar cuál fue la solución final. Agregar ícono con título en CollapsingToolbarLayout
Y finalmente esta debería ser una biblioteca de trabajo que hace el trabajo. Lo he comprobado, pero la imagen inicial no estaba centrada y preferí trabajar en el ejemplo de perro que había visto antes. Consulte https://github.com/datalink747/CollapsingAvatarToolbar
Más para leer
http://saulmm.github.io/mastering-coordinator http://www.androidauthority.com/using-coordinatorlayout-android-apps-703720/ https://developer.android.com/reference/android/support/design/widget/CoordinatorLayout.html https://guides.codepath.com/android/handling-scrolls-with-coordinatorlayout