android - ubicación - ¿Cómo imitar el comportamiento de 3 fases de la hoja inferior de Google Maps?
ubicacion actual (4)
¿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 la hoja inferior.
ACTUALIZAR:
Básicamente el enlace dice:
Al adjuntar un BottomSheetBehavior a una Vista secundaria de un CoordinatorLayout (es decir, agregar la aplicación: layout_behavior = "android.support.design.widget.BottomSheetBehavior"), obtendrá automáticamente la detección táctil adecuada para la transición entre cinco estados:
STATE_COLLAPSED: this collapsed state is the default and shows just a portion of the layout along the bottom. The height can be controlled with the app:behavior_peekHeight attribute (defaults to 0)
STATE_DRAGGING: the intermediate state while the user is directly dragging the bottom sheet up or down
STATE_SETTLING: that brief time between when the View is released and settling into its final position
STATE_EXPANDED: the fully expanded state of the bottom sheet, where either the whole bottom sheet is visible (if its height is less than the containing CoordinatorLayout) or the entire CoordinatorLayout is filled
STATE_HIDDEN: disabled by default (and enabled with the app:behavior_hideable attribute), enabling this allows users to swipe down on the bottom sheet to completely hide the bottom sheet
Keep in mind that scrolling containers in your bottom sheet must support nested scrolling (for example, NestedScrollView, RecyclerView, or ListView/ScrollView on API 21+).
Si desea recibir devoluciones de llamada de cambios de estado, puede agregar un BottomSheetCallback:
// The View with the BottomSheetBehavior
View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
// React to state change
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// React to dragging events
}
});
Si bien BottomSheetBehavior captura el caso de la hoja inferior persistente, esta versión también proporciona un BottomSheetDialog y BottomSheetDialogFragment para llenar el caso de uso modal de las hojas inferiores. Simplemente reemplace AppCompatDialog o AppCompatDialogFragment con sus equivalentes en la hoja inferior para que su diálogo tenga el estilo de una hoja inferior.
Fondo
Estoy asignado a hacer una interfaz de usuario que se comporte de manera similar a cómo Google Maps muestra una hoja de resultados para un resultado encontrado.
Tiene tres fases diferentes:
- Contenido inferior El área superior todavía se puede tocar y no 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 tiene solo la barra de herramientas.
Esto es de lo que estoy hablando en Google Maps:
El problema
La cuestión es que la hoja inferior todavía no forma parte de la biblioteca de diseño (aunque se solicitó here ).
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 intentado
Encontré una buena (suficiente) biblioteca para la hoja inferior ( here ), y agregué contenido a su muestra de fragmentos, para tener aproximadamente las mismas vistas que se muestran en las muestras de diseño de material (como here ), 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 icono a medida que 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é tiene de malo el código? ¿Qué puedo hacer para lograr el comportamiento requerido?
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 parecía envolver el contenido ni del encabezado ni el contenido desplazable a pesar de especificar
wrap_content
.
Ese problema desapareció cuando utilicé
LinearLayout
lugar de
ConstraintLayout
para el diseño secundario de
CoordinatorLayout
(y para sus elementos secundarios).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/buttonPeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Peek"
app:layout_constraintEnd_toStartOf="@+id/buttonExpand"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonExpand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expand"
app:layout_constraintEnd_toStartOf="@+id/buttonClose"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/buttonPeek"
app:layout_constraintTop_toTopOf="@+id/buttonPeek" />
<Button
android:id="@+id/buttonClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/buttonExpand"
app:layout_constraintTop_toTopOf="@+id/buttonExpand" />
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_coordinator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/layout_coordinator_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:layout_behavior="@string/bottom_sheet_behavior">
<LinearLayout
android:id="@+id/layout_bottom_sheet_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFF0000"
android:orientation="vertical" >
<TextView
android:id="@+id/headerTextView_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="a" />
<TextView
android:id="@+id/headerTextView_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="b" />
<TextView
android:id="@+id/headerTextView_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="c" />
<TextView
android:id="@+id/headerTextView_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="d" />
<TextView
android:id="@+id/headerTextView_e"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="e" />
<TextView
android:id="@+id/headerTextView_f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="f" />
<TextView
android:id="@+id/headerTextView_g"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="g" />
<TextView
android:id="@+id/headerTextView_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="h" />
<TextView
android:id="@+id/headerTextView_i"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="i" />
<TextView
android:id="@+id/headerTextView_j"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="j" />
<TextView
android:id="@+id/headerTextView_k"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="k" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/layout_bottom_sheet_scrollable_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF00FF00"
android:fillViewport="true" >
<LinearLayout
android:id="@+id/layout_bottom_sheet_scrollable_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="6" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="7" />
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="8" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="9" />
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10" />
<TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11" />
<TextView
android:id="@+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="12" />
<TextView
android:id="@+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="13" />
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="14" />
<TextView
android:id="@+id/textView15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15" />
<TextView
android:id="@+id/textView16"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="16" />
<TextView
android:id="@+id/textView17"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="17" />
<TextView
android:id="@+id/textView18"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="18" />
<TextView
android:id="@+id/textView19"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="19" />
<TextView
android:id="@+id/textView20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="20" />
<TextView
android:id="@+id/textView21"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="21" />
<TextView
android:id="@+id/textView22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="22" />
<TextView
android:id="@+id/textView23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="23" />
<TextView
android:id="@+id/textView24"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="24" />
<TextView
android:id="@+id/textView25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25" />
<TextView
android:id="@+id/textView26"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="26" />
<TextView
android:id="@+id/textView27"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="27" />
<TextView
android:id="@+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="28" />
<TextView
android:id="@+id/textView29"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="29" />
<TextView
android:id="@+id/textView30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30" />
<TextView
android:id="@+id/textView31"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="31" />
<TextView
android:id="@+id/textView32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="32" />
<TextView
android:id="@+id/textView33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="33" />
<TextView
android:id="@+id/textView34"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="34" />
<TextView
android:id="@+id/textView35"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="35" />
<TextView
android:id="@+id/textView36"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="36" />
<TextView
android:id="@+id/textView37"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="37" />
<TextView
android:id="@+id/textView38"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="38" />
<TextView
android:id="@+id/textView39"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="39" />
<TextView
android:id="@+id/textView40"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="40" />
<TextView
android:id="@+id/textView41"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="41" />
<TextView
android:id="@+id/textView42"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="42" />
<TextView
android:id="@+id/textView43"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="43" />
<TextView
android:id="@+id/textView44"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="44" />
<TextView
android:id="@+id/textView45"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="45" />
<TextView
android:id="@+id/textView46"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="46" />
<TextView
android:id="@+id/textView47"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="47" />
<TextView
android:id="@+id/textView48"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="48" />
<TextView
android:id="@+id/textView49"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="49" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.bottomsheetwithscrollablecontent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import androidx.appcompat.app.AppCompatActivity;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
public class MainActivity extends AppCompatActivity {
private CoordinatorLayout layout_coordinator;
private View layout_coordinator_child;
private View layout_bottom_sheet_header;
private BottomSheetBehavior behavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout_coordinator = findViewById(R.id.layout_coordinator);
layout_coordinator_child = layout_coordinator.findViewById(R.id.layout_coordinator_child);
layout_bottom_sheet_header = layout_coordinator.findViewById(R.id.layout_bottom_sheet_header);
behavior = BottomSheetBehavior.from(layout_coordinator_child);
Button buttonPeek = findViewById(R.id.buttonPeek);
buttonPeek.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setPeekHeight(layout_bottom_sheet_header.getHeight());
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
Button buttonExpand = findViewById(R.id.buttonExpand);
buttonExpand.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
Button buttonClose = findViewById(R.id.buttonClose);
buttonClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
});
}
}
app / build.gradle
apply plugin: ''com.android.application''
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.bottomsheetwithscrollablecontent"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(''proguard-android-optimize.txt''), ''proguard-rules.pro''
}
}
}
dependencies {
implementation fileTree(dir: ''libs'', include: [''*.jar''])
implementation ''androidx.appcompat:appcompat:1.0.0-beta01''
implementation ''androidx.constraintlayout:constraintlayout:1.1.2''
testImplementation ''junit:junit:4.12''
androidTestImplementation ''androidx.test:runner:1.1.0-alpha4''
androidTestImplementation ''androidx.test.espresso:espresso-core:3.1.0-alpha4''
implementation ''androidx.legacy:legacy-support-v4:1.0.0-beta01''
implementation "com.google.android.material:material:1.1.0-alpha04"
}
GRAN ACTUALIZACIÓN
Debido a que había como 4 o 5 preguntas sobre el mismo tema, PERO con DIFERENTES requisitos, e intenté responderlos a todos, pero un administrador no educado los eliminó / cerró, lo que me hizo crear un ticket para cada uno y cambiarlos a evite "copiar y pegar". Le dejaré un enlace a la respuesta completa en la que puede encontrar toda la explicación sobre cómo obtener un comportamiento completo como Google Maps.
Respondiendo tu pregunta
¿Cómo imitar el comportamiento de 3 fases de la hoja inferior de Google Maps?
Con la biblioteca de soporte 23.x.x +, puede hacerlo modificando el
BottomSheetBehavior
predeterminado, agregando una estadística más con los siguientes pasos:
-
Cree una clase Java y extiéndala desde
CoordinatorLayout.Behavior<V>
-
Copie el código de
BottomSheetBehavior
archivoBottomSheetBehavior
predeterminado a su nuevo. -
Modifique el método
clampViewPositionVertical
con el siguiente código:@Override public int clampViewPositionVertical(View child, int top, int dy) { return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset); } int constrain(int amount, int low, int high) { return amount < low ? low : (amount > high ? high : amount); }
-
Agregar un nuevo estado:
public static final int STATE_ANCHOR_POINT = X;
-
Modifique los siguientes 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:
Nota : lea las ediciones en la parte inferior
OK, he encontrado una manera de hacerlo, pero tuve que cambiar el código de varias clases, para que la hoja inferior supiera el estado de appBarLayout (expandido o no) e ignore el desplazamiento hacia arriba en caso de que sea no expandido:
BottomSheetLayout.java
Campos agregados:
private AppBarLayout mAppBarLayout;
private OnOffsetChangedListener mOnOffsetChangedListener;
private int mAppBarLayoutOffset;
init () - agregó esto:
mOnOffsetChangedListener = new OnOffsetChangedListener() {
@Override
public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) {
mAppBarLayoutOffset = verticalOffset;
}
};
Función agregada para configurar la aplicaciónBarLayout:
public void setAppBarLayout(final AppBarLayout appBarLayout) {
if (mAppBarLayout == appBarLayout)
return;
if (mAppBarLayout != null)
mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
mAppBarLayout = appBarLayout;
mAppBarLayout.addOnOffsetChangedListener(mOnOffsetChangedListener);
}
onDetachedFromWindow () - agregó esto:
if (mAppBarLayout != null)
mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
onTouchEvent () - agregó esto:
...
if (bottomSheetOwnsTouch) {
if (state == State.EXPANDED && scrollingDown && mAppBarLayout != null && mAppBarLayoutOffset != 0) {
event.offsetLocation(0, sheetTranslation - getHeight());
getSheetView().dispatchTouchEvent(event);
return true;
}
...
Esos fueron los principales cambios. Ahora para lo que los establece:
MyFragment.java
onCreateView () - agregó esto:
mBottomSheetLayout.setAppBarLayout((AppBarLayout) view.findViewById(R.id.appbar));
También agregué esta función:
public void setBottomSheetLayout(final BottomSheetLayout bottomSheetLayout) {
mBottomSheetLayout = bottomSheetLayout;
}
Ahora así es como la actividad le dice al fragmento sobre appBarLayout:
final MyFragment myFragment = new MyFragment();
myFragment.setBottomSheetLayout(bottomSheetLayout);
myFragment.show(getSupportFragmentManager(), R.id.bottomsheet);
El proyecto ya está disponible en GitHub:
https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet
Espero que no tenga ningún error.
La solución tiene errores, lamentablemente, por lo que no marcaré esta respuesta como la correcta:
- Solo funciona bien en Android 6 y superior. Otros tienen un comportamiento extraño al mostrar la hoja inferior expandida durante una pequeña fracción de tiempo, cada vez que se muestra.
- Los cambios de orientación no guardan el estado del desplazamiento en absoluto, así que lo he desactivado.
- Problema raro de poder desplazarse dentro del contenido de la hoja inferior mientras todavía está colapsado (en la parte inferior)
- Si se mostró un teclado antes, la hoja inferior podría aparecer en pantalla completa cuando se trata de mirar.
Si alguien puede ayudarlo, por favor hágalo.
Para el problema n. ° 1, intenté agregar una solución al configurar la visibilidad como INVISIBLE cuando la hoja inferior aún no se asoma, pero no siempre funciona, especialmente si se muestra un teclado.
Para el problema # 1, he encontrado cómo solucionarlo, simplemente envolviendo (en "fragment_my.xml") el CoordinatorLayout con cualquier vista que desee usar (usé FrameLayout), y también coloque una vista de tamaño completo en (acabo de poner "Ver"), como tal:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--This full sized view, together with the FrameLayout above, are used to handle some weird UI issues on pre-Android-6 -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<...CollapsingToolbarLayout
...
Probablemente confundió el bottomSheet cuando tuve el CoordinatorLayout siendo su punto de vista. He actualizado el proyecto, pero aún así, si hay alguna forma de tener una solución más agradable, me gustaría saberlo.
En los últimos meses, Google ha publicado su propia clase bottomSheet, pero como he encontrado tiene muchos problemas, por lo que ni siquiera puedo probarlo.