Antecedentes
Me asignaron crear una interfaz de usuario que se comporte de manera similar a cómo Google Maps muestra una hoja inferior para un resultado encontrado.
Tiene tres fases diferentes:
- Contenido inferior. El área superior aún se puede tocar y no se desplazará nada en la parte inferior
- Contenido de pantalla completa, mientras que el área superior tiene un encabezado grande.
- Contenido de pantalla completa, mientras que el área superior solo tiene la barra de herramientas.
Esto es de lo que estoy hablando en Google Maps:
El problema
La cuestión es que la hoja inferior aún no forma parte de la biblioteca de diseño (aunque se solicitó aquí ).
No solo eso, sino que la interfaz de usuario parece bastante compleja y necesita el manejo de la barra de herramientas en múltiples fases.
Lo que he probado
Encontré una biblioteca buena (suficiente) para la hoja inferior ( aquí ), y agregué contenido a su muestra de fragmento, para tener aproximadamente las mismas vistas que se muestran en las muestras de diseño de materiales (como aquí ), para tener un CollapsingToolbarLayout que se encargará de las fases 2 + 3.
En la aplicación que estoy creando, también tengo que mover un ícono mientras te desplazas, pero creo que si tengo éxito con el resto, esto debería ser fácil. Aquí está el código:
fragment_my.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
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/appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
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"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/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.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/card_margin"
android:layout_marginLeft="@dimen/card_margin"
android:layout_marginRight="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Friends"
android:textAppearance="@style/TextAppearance.AppCompat.Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/card_margin"
android:layout_marginLeft="@dimen/card_margin"
android:layout_marginRight="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Related"
android:textAppearance="@style/TextAppearance.AppCompat.Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"
android:src="@android:drawable/ic_menu_send"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
MyFragment.java
public class MyFragment extends BottomSheetFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_my, container, false);
view.setMinimumHeight(getResources().getDisplayMetrics().heightPixels);
CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("AAA");
final Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
final AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavUtils.navigateUpFromSameTask(getActivity());
}
});
final ImageView imageView = (ImageView) view.findViewById(R.id.backdrop);
Glide.with(this).load(R.drawable.cheese_1).centerCrop().into(imageView);
return view;
}
}
BottomSheetFragmentActivity.java
public final class BottomSheetFragmentActivity extends AppCompatActivity {
protected BottomSheetLayout bottomSheetLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_sheet_fragment);
bottomSheetLayout = (BottomSheetLayout) findViewById(R.id.bottomsheet);
findViewById(R.id.bottomsheet_fragment_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MyFragment().show(getSupportFragmentManager(), R.id.bottomsheet);
}
});
bottomSheetLayout.setShouldDimContentView(false);
bottomSheetLayout.setPeekOnDismiss(true);
bottomSheetLayout.setPeekSheetTranslation(200);
bottomSheetLayout.setInterceptContentTouch(false);
bottomSheetLayout.setDefaultViewTransformer(new BaseViewTransformer() {
@Override
public void transformView(final float translation, final float maxTranslation, final float peekedTranslation, final BottomSheetLayout parent, final View view) {
Log.d("AppLog", "translation:" + translation + " maxTranslation:" + maxTranslation + " peekedTranslation:" + peekedTranslation);
}
});
}
}
Casi funciona bien. El único problema es la transición del n. ° 3 al n. ° 2:
La pregunta
¿Qué pasa con el código? ¿Qué puedo hacer para lograr el comportamiento requerido?
fuente
CoordinatorLayout
en la segunda pantalla?Respuestas:
Nota : lea las ediciones en la parte inferior
OK, encontré una manera de hacerlo, pero tuve que cambiar el código de varias clases, para que la hoja inferior conociera el estado de appBarLayout (expandido o no) e ignorar el desplazamiento hacia arriba en caso de que sea no expandido:
BottomSheetLayout.java
Campos agregados:
init () - agregó esto:
Función agregada para configurar el appBarLayout:
onDetachedFromWindow () - agregó esto:
onTouchEvent () - agregó esto:
Esos fueron los principales cambios. Ahora, por lo que los establece:
MyFragment.java
onCreateView () - agregó esto:
También agregué esta función:
Ahora, así es como la actividad le dice al fragmento sobre el appBarLayout:
El proyecto ahora está disponible en GitHub:
https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet
Espero que no tenga errores.
La solución tiene errores, lamentablemente, así que no marcaré esta respuesta como la correcta:
Si alguien puede ayudarlo, hágalo.
Para el problema n. ° 1, intenté agregar una solución configurando la visibilidad en INVISIBLE cuando la hoja inferior aún no se ve, pero no siempre funciona, especialmente si se muestra un teclado.
Para el problema n. ° 1, encontré cómo solucionarlo, simplemente ajustando (en "fragment_my.xml") el CoordinatorLayout con cualquier vista que desee usar (usé FrameLayout), y también coloqué una vista de tamaño completo en it (acabo de poner "Ver"), como tal:
Probablemente confundió la hoja inferior cuando tenía el CoordinatorLayout como su vista. Actualicé el proyecto, pero aún así, si hay alguna forma de tener una mejor solución, me gustaría saberlo.
En los últimos meses, Google ha publicado su propia clase bottomSheet, pero he descubierto que tiene muchos problemas, por lo que ni siquiera puedo probarlo.
fuente
GRAN ACTUALIZACIÓN
Porque había como 4 o 5 preguntas sobre el mismo tema, PERO con DIFERENTES requisitos, y traté de responder a todos, pero un administrador no educado los eliminó / cerró, lo que me obligó a crear un ticket para cada uno y cambiarlos a Evite "copiar y pegar". Le dejaré un enlace a la respuesta completa en donde puede encontrar toda la explicación sobre cómo obtener un comportamiento completo como Google Maps.
Respondiendo tu pregunta
Con la biblioteca de soporte 23.x.x + puedes hacerlo modificando la predeterminada
BottomSheetBehavior
, agregando una estadística más con los siguientes pasos:CoordinatorLayout.Behavior<V>
BottomSheetBehavior
archivo predeterminado al nuevo.Modifique el método
clampViewPositionVertical
con el siguiente código:Agregar un nuevo estado:
Modificar los próximos métodos:
onLayoutChild
,onStopNestedScroll
,BottomSheetBehavior<V> from(V view)
ysetState
(opcional)Voy a agregar esos métodos modificados y un enlace al proyecto de ejemplo .
Y así es como se ve:
fuente
CoordinatorLayout
inactivity_main.xml
. Supongo que tiene una buena experiencia con el diseño del coordinador, de lo contrario, eche un vistazo a este enlace que encontré¿Intentaste esto? http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1 Aquí dice que podemos especificar un comportamiento de diseño de hoja inferior.
ACTUALIZAR:
Básicamente, el enlace dice:
Al adjuntar un BottomSheetBehavior a una Vista secundaria de un CoordinatorLayout (es decir, agregar app: layout_behavior = "android.support.design.widget.BottomSheetBehavior"), automáticamente obtendrá la detección táctil adecuada para la transición entre cinco estados:
Si desea recibir devoluciones de llamada de los cambios de estado, puede agregar un BottomSheetCallback:
Si bien BottomSheetBehavior captura el caso de la hoja inferior persistente, esta versión también proporciona un BottomSheetDialog y BottomSheetDialogFragment para completar el caso de uso modal de las hojas inferiores. Simplemente reemplace AppCompatDialog o AppCompatDialogFragment con sus equivalentes en la hoja inferior para que su cuadro de diálogo tenga el estilo de una hoja inferior.
fuente
También tuve que implementar una vista similar a cómo Google Maps muestra una hoja inferior para un resultado encontrado.
Así es como se ve el mío:
Al principio, definí una hoja inferior con un encabezado y contenido desplazable, pero el layout_height no pareció envolver el contenido ni del encabezado ni del contenido desplazable a pesar de especificar
wrap_content
.Ese problema desapareció cuando usé en
LinearLayout
lugar deConstraintLayout
para elCoordinatorLayout
diseño secundario de (y para sus elementos secundarios).activity_main.xml
MainActivity.java
app / build.gradle
fuente