RecyclerView Expandir / Contraer elementos
Quiero expandir / contraer los elementos de mi recicladorVer para mostrar más información. Quiero lograr el mismo efecto de la SlideExpandableListView .
Básicamente, en mi viewHolder tengo una vista que no es visible y quiero hacer una suave expansión / colapso animación en lugar de establecer la visibilidad a VISIBLE / GONE sólo. Sólo necesito un elemento para ser ampliado a la vez y sería genial tener alguna elevación para mostrar que el elemento está seleccionado.
- Cómo decorar selectivamente los elementos de RecyclerView
- Centro Horizontal última fila utilizando span Recycler GridLayoutManager
- Animar transiciones de elementos compartidos usando fragmentos de Android parece ser una pesadilla
- Datos de SQLite a un RecyclerView
- Implementación diferente para un botón de acción flotante en cada fragmento de una actividad
Es el mismo efecto de la nueva lista de historias de llamadas recientes de Android. Las opciones "CALL BACK" y "DETAILS" sólo están visibles cuando se selecciona un elemento.
- HorizontalGridView / RecyclerLa posición de desplazamiento se restablece una vez que la imagen de Picasso se carga
- Práctica recomendada para eliminar asincrónicamente un elemento ListView / RecyclerView
- RecyclerView no se actualiza después de NotifyDataSetChanged (), el contenido aparece después de encender y apagar la pantalla
- Navegación (Siguiente) con EditText en un ListView / RecyclerView
- Android notifyItemRangeInserted deshabilitar autoscroll
- RecyclerView: java.lang.IndexOutOfBoundsException: Inconsistencia detectada. Posición de artículo no válida
- RecyclerView autofit LayoutManager
- Deslizar hacia abajo para actualizar el diseño del material
Por favor, no utilice ninguna biblioteca para este efecto en su lugar utilice la forma recomendada de hacerlo de acuerdo con Google I / O 2016. En el método onBindViewHolder de recyclerView, haga lo siguiente:
final boolean isExpanded = position==mExpandedPosition; holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE); holder.itemView.setActivated(isExpanded); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mExpandedPosition = isExpanded ? -1:position; TransitionManager.beginDelayedTransition(recyclerView); notifyDataSetChanged(); } });
- Donde detalles es mi vista que se mostrará en el tacto (detalles de la llamada en su caso. Visibilidad predeterminada.GONE).
- MExpandedPosition es una variable int inicializada a -1
Y para los efectos especiales que querías, utiliza estos como tus atributos list_item:
android:background="@drawable/comment_background" android:stateListAnimator="@animator/comment_selection"
Donde comment_background es:
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true" android:enterFadeDuration="@android:integer/config_shortAnimTime" android:exitFadeDuration="@android:integer/config_shortAnimTime"> <item android:state_activated="true" android:drawable="@color/selected_comment_background" /> <item android:drawable="@color/comment_background" />
Y comment_selection es:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="true"> <objectAnimator android:propertyName="translationZ" android:valueTo="@dimen/z_card" android:duration="@android:integer/config_shortAnimTime" android:interpolator="@android:interpolator/fast_out_slow_in" /> </item> <item> <objectAnimator android:propertyName="translationZ" android:valueTo="0dp" android:duration="@android:integer/config_shortAnimTime" android:interpolator="@android:interpolator/fast_out_slow_in" /> </item>
No decir que este es el mejor enfoque, pero parece que funciona para mí.
El código completo se puede encontrar en: Código de ejemplo en: https://github.com/dbleicher/recyclerview-grid-quickreturn
Primero, agregue el área expandida a su diseño de celda / elemento, y haga el diseño de celda que lo envuelve. AnimateLayoutChanges = "true". Esto asegurará que la expansión / colapso se anima:
<LinearLayout android:id="@+id/llCardBack" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:animateLayoutChanges="true" android:padding="4dp" android:orientation="vertical"> <TextView android:id="@+id/tvTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center|fill_horizontal" android:padding="10dp" android:gravity="center" android:background="@android:color/holo_green_dark" android:text="This is a long title to show wrapping of text in the view." android:textColor="@android:color/white" android:textSize="16sp" /> <TextView android:id="@+id/tvSubTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center|fill_horizontal" android:background="@android:color/holo_purple" android:padding="6dp" android:text="My subtitle..." android:textColor="@android:color/white" android:textSize="12sp" /> <LinearLayout android:id="@+id/llExpandArea" android:visibility="gone" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="Item One" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="Item Two" /> </LinearLayout> </LinearLayout>
A continuación, haga que su clase RV Adapter implemente View.OnClickListener para que pueda actuar sobre el elemento al que se hace clic. Agregue un campo int para mantener la posición de una vista expandida e inicialícela a un valor negativo:
private int expandedPosition = -1;
Finalmente, implemente sus métodos ViewHolder, onBindViewHolder () y reemplace el método onClick (). Usted ampliará la vista en onBindViewHolder si su posición es igual a "expandedPosition", y ocultarlo si no. Se establece el valor de expandedPosition en el listener onClick:
@Override public void onBindViewHolder(RVAdapter.ViewHolder holder, int position) { int colorIndex = randy.nextInt(bgColors.length); holder.tvTitle.setText(mDataset.get(position)); holder.tvTitle.setBackgroundColor(bgColors[colorIndex]); holder.tvSubTitle.setBackgroundColor(sbgColors[colorIndex]); if (position == expandedPosition) { holder.llExpandArea.setVisibility(View.VISIBLE); } else { holder.llExpandArea.setVisibility(View.GONE); } } @Override public void onClick(View view) { ViewHolder holder = (ViewHolder) view.getTag(); String theString = mDataset.get(holder.getPosition()); // Check for an expanded view, collapse if you find one if (expandedPosition >= 0) { int prev = expandedPosition; notifyItemChanged(prev); } // Set the current position to "expanded" expandedPosition = holder.getPosition(); notifyItemChanged(expandedPosition); Toast.makeText(mContext, "Clicked: "+theString, Toast.LENGTH_SHORT).show(); } /** * Create a ViewHolder to represent your cell layout * and data element structure */ public static class ViewHolder extends RecyclerView.ViewHolder { TextView tvTitle; TextView tvSubTitle; LinearLayout llExpandArea; public ViewHolder(View itemView) { super(itemView); tvTitle = (TextView) itemView.findViewById(R.id.tvTitle); tvSubTitle = (TextView) itemView.findViewById(R.id.tvSubTitle); llExpandArea = (LinearLayout) itemView.findViewById(R.id.llExpandArea); } }
Esto debe expandir sólo un elemento a la vez, utilizando la animación predeterminada del sistema para el cambio de diseño. Al menos funciona para mí. Espero eso ayude.
Hay una biblioteca muy simple de usar con soporte de gradle: https://github.com/cachapa/ExpandableLayout .
Desde la biblioteca docs:
<net.cachapa.expandablelayout.ExpandableLinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:el_duration="1000" app:el_expanded="true"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Click here to toggle expansion" /> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:text="Fixed height" app:layout_expandable="true" /> </net.cachapa.expandablelayout.ExpandableLinearLayout>
Después de marcar sus vistas expandibles , simplemente llame a cualquiera de estos métodos en el contenedor: expand()
, collapse()
o toggle()
Puede utilizar ExpandableLayout. https://github.com/KyoSherlock/ExpandableLayout
Este ExpandableLayout es como una suave expansión / contracción CheckBox animación, por lo que se puede utilizar en cualquier lugar (ListView o RecyclerView).
Haga lo siguiente después de establecer el listener onClick en la clase ViewHolder:
@Override public void onClick(View v) { final int originalHeight = yourLinearLayout.getHeight(); animationDown(YourLinearLayout, originalHeight);//here put the name of you layout that have the options to expand. } //Animation for devices with kitkat and below public void animationDown(LinearLayout billChoices, int originalHeight){ // Declare a ValueAnimator object ValueAnimator valueAnimator; if (!billChoices.isShown()) { billChoices.setVisibility(View.VISIBLE); billChoices.setEnabled(true); valueAnimator = ValueAnimator.ofInt(0, originalHeight+originalHeight); // These values in this method can be changed to expand however much you like } else { valueAnimator = ValueAnimator.ofInt(originalHeight+originalHeight, 0); Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out a.setDuration(200); // Set a listener to the animation and configure onAnimationEnd a.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { billChoices.setVisibility(View.INVISIBLE); billChoices.setEnabled(false); } @Override public void onAnimationRepeat(Animation animation) { } }); // Set the animation on the custom view billChoices.startAnimation(a); } valueAnimator.setDuration(200); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); billChoices.getLayoutParams().height = value.intValue(); billChoices.requestLayout(); } }); valueAnimator.start(); } }
Creo que debería ayudar, así es como lo implementé y lo hace el mismo google en la vista de llamadas recientes.
Utilice dos tipos de vista en su RVAdapter
. Uno para ampliar el diseño y otros para colapsar. Y la magia sucede con la configuración de android:animateLayoutChanges="true"
para RecyclerView
Checkout el efecto logrado con esto a las 0:42 en este video