android - coordinatorlayout - layout_collapsemode
¿Cómo deshabilitar el desplazamiento de NestedScrollView & CollapsingToolbarLayout, por ejemplo cuando no hay más contenido a continuación? (2)
Antecedentes
Intento agregar la misma funcionalidad que se muestra en muchas aplicaciones, donde el área superior de la pantalla se reduce y se expande de acuerdo con el contenido desplazado.
Para esto, uso la biblioteca de diseño de Google, como se muestra en la muestra CheeseSquare .
El problema
La cuestión es que, sin importar cuánto contenido haya en NestedScrollView, me permite desplazarme mucho más abajo de la última vista del contenido, solo para permitirme ver el estado final de la barra de acción, que tiene el tamaño mínimo de sí mismo.
En resumen, esto es lo que veo cuando me desplazo hacia abajo (contenido modificado de la muestra CheeseSquare):
Si bien esto es lo que me gustaría tener al desplazarme hacia abajo (tomado de la aplicación de contactos):
También estoy tratando de corregir un error en la muestra ThreePhasesBottomSheet que es posible desplazarse en el contenido de la hoja inferior incluso cuando está en estado de peek. Para reproducir, comience a desplazarse horizontalmente (que no hace nada, ya que no hay nada que desplazarse de esta manera) y luego verticalmente, lo que de alguna manera desencadenaría el desplazamiento del contenido de la hoja inferior.
Por lo tanto, necesito deshabilitar el desplazamiento en el método "transformView ()", en el caso de que "traducción
Así es como funciona usando el uso normal:
Y así es como se comporta con el error de no bloquear el desplazamiento:
Lo que he intentado
Intenté jugar con las banderas " layout_scrollFlags ", para cambiar la altura a wrap_content y para eliminar los atributos clipToPadding y fitsSystemWindows.
Aquí está el archivo XML de muestra, que he modificado para incluir solo un cardView en lugar de muchos:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
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="@dimen/detail_backdrop_height"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</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>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
android:src="@drawable/ic_discuss"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"/>
</android.support.design.widget.CoordinatorLayout>
También probé el siguiente código:
((AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams()).setScrollFlags(0);
pero esto todavía permitía desplazarse por el NestedScrollView en sí mismo en el ejemplo CheeseSquare , y también permitía arrojar en el ejemplo ThreePhasesBottomSheet .
Las preguntas
-
¿Qué puedo hacer para detener el desplazamiento cuando no hay más contenido para mostrar en la parte inferior?
-
Además, ¿qué se puede hacer para deshabilitar el desplazamiento de NestedScrollView en cualquier momento que desee (para el ejemplo ThreePhasesBottomSheet )? ¿Algo así como "setEnableScrolling (...)"?
Traté de extender NestedScrollView y también de ScrollingViewBehavior, pero no pude encontrar qué se puede hacer para deshabilitar el desplazamiento.
Probablemente sea algo muy simple de cambiar, pero no puedo descubrir qué ...
EDITAR: si es necesario, esto es lo que uso actualmente para la biblioteca de diseño y soporte
compile ''com.android.support:appcompat-v7:23.1.0''
compile ''com.android.support:design:23.1.0''
EDITAR: para el n. ° 2, he encontrado una solución dentro del archivo BottomSheetLayout.java, para deshabilitar todo lo relacionado con la variable "sheetViewOwnsTouch", como si siempre estuviera configurado como "falso". Esto permitirá robar eventos táctiles en la hoja inferior. Sin embargo, esto es solo una solución, y solo para este caso. También provoca algunos eventos táctiles que deberían haber sido manejados por otras vistas. Todavía deseo saber cómo bloquear el desplazamiento mediante programación, y también en el otro caso de suficiente espacio para mostrar el contenido.
¿Qué puedo hacer para detener el desplazamiento cuando no hay más contenido para mostrar en la parte inferior?
En primer lugar, como he comentado a continuación, el desplazamiento que dijiste en tu pregunta no es de
NestedScrollView
.
Pertenece a
CollapsingToolbarLayout
.
El evento de desplazamiento de
NestedScrollView
solo ocurre cuando
CollapsingToolbarLayout
se contrae por completo y, por supuesto, dejará de desplazarse cuando no haya más contenido dentro (fondo alcanzado).
Para
CollapsingToolbarLayout
, colapsará a la altura de diseño de su Barra de herramientas (como en el archivo xml, encontrará
"?attr/actionBarSize"
).
La siguiente imagen demostrará que, preste atención al rectangular rojo que es la barra de herramientas (configuré su fondo)
Entonces, para tener una solución para su # 1, necesita calcular la altura de
NestedScrollView
, luego, si es más pequeña que la altura de la pantalla, arreglamos la altura de la barra de herramientas.
En resumen, puede actualizar
activity_detail.xml
la siguiente manera:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
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="@dimen/detail_backdrop_height"
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:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
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="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<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>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
Y CheeseDetailActivity.java:
public class CheeseDetailActivity extends AppCompatActivity {
public static final String EXTRA_NAME = "cheese_name";
private final Context mContext = this;
private int screenHeight;
private int linearLayoutHeight;
private int toolbarHeight_org;
private int toolbarHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Intent intent = getIntent();
final String cheeseName = intent.getStringExtra(EXTRA_NAME);
screenHeight = getScreenHeight(this);
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
final int colorPrimary = typedValue.data;
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
final CoordinatorLayout.LayoutParams appbarLayoutParams = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
final ViewGroup.LayoutParams toolbarLayoutParams = toolbar.getLayoutParams();
if (toolbarLayoutParams != null) {
toolbarHeight_org = toolbarLayoutParams.height;
toolbarHeight = toolbarLayoutParams.height;
}
final CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(cheeseName);
collapsingToolbar.setContentScrimColor(colorPrimary);
collapsingToolbar.setExpandedTitleTextAppearance(R.style.ExpandedTitleTextAppearance);
//collapsingToolbar.setCollapsedTitleTextAppearance(R.style.CollapsedTitleTextAppearance);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout1);
ViewTreeObserver observer = linearLayout.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
linearLayoutHeight = linearLayout.getHeight();
if (linearLayoutHeight + toolbarHeight < screenHeight) {
if (toolbarLayoutParams != null) {
toolbarLayoutParams.height = screenHeight - linearLayoutHeight - 20;
if (toolbarLayoutParams.height < toolbarHeight_org) {
toolbarLayoutParams.height = toolbarHeight_org;
}
int extended_text_size = (int) getResources().getDimension(R.dimen.expanded_text_size);
if (appbarLayoutParams.height - toolbarLayoutParams.height <= extended_text_size) {
int value = appbarLayoutParams.height - toolbarLayoutParams.height;
if (value < 0) {
appbarLayoutParams.height = toolbarLayoutParams.height - value + extended_text_size * 3;
} else {
appbarLayoutParams.height = toolbarLayoutParams.height + extended_text_size * 3;
}
if (appbarLayoutParams.height >= screenHeight) {
appbarLayoutParams.height = screenHeight;
}
}
// collapsingToolbar.setContentScrimColor(getResources().getColor(android.R.color.transparent));
if (toolbarLayoutParams.height > toolbarHeight_org) {
collapsingToolbar.setContentScrimColor(ContextCompat.getColor(mContext, android.R.color.transparent));
}
}
}
// Removes the listener if possible
ViewTreeObserver viewTreeObserver = linearLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
});
loadBackdrop();
appbar.setExpanded(true);
}
private int getScreenHeight(Context context) {
int measuredHeight;
Point size = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
wm.getDefaultDisplay().getSize(size);
measuredHeight = size.y;
} else {
Display d = wm.getDefaultDisplay();
measuredHeight = d.getHeight();
}
return measuredHeight;
}
private void loadBackdrop() {
final ImageView imageView = (ImageView) findViewById(R.id.backdrop);
Glide.with(this).load(Cheeses.getRandomCheeseDrawable()).centerCrop().into(imageView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_actions, menu);
return true;
}
}
Aquí está el resultado:
Con la muestra Cheesesquare , he personalizado este proyecto y lo he subido a My GitHub . Estoy de acuerdo en que todavía tiene algunos problemas, sin embargo, al menos puede ser una solución para su primer problema.
Por favor echa un vistazo. ¡Espero eso ayude!
Para deshabilitar el desplazamiento, simplemente configure NestedScrollView y su altura secundaria LinearLayout en ''wrap_content''.
Eso no funcionará completamente como lo desea, pero al menos no será desplazable, si el contenido se ajusta completamente en la pantalla.
Hablando del ejemplo de su aplicación Contactos, parece que no está usando CoordinatorLayout y otras cosas que vienen con él.
Este comportamiento se puede hacer de esta manera:
<ScrollView
android:id="@+id/scroll_adinfo"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="@dimen/image_height"
android:src="@mipmap/ic_launcher"/>
<LinearLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/image_height">
<!-- YOUR CONTENT HERE -->
</LinearLayout>
</FrameLayout>
</ScrollView>
Y en su código moverá la imagen en el desplazamiento:
final ImageView image = (ImageView) findViewById(R.id.image);
((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getViewTreeObserver().addOnScrollChangedListener(
new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
int scrollY = ((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getScrollY();
image.setY(scrollY / 2);
}
});
Extraje eso de uno de mis proyectos y lo edité para que pueda perder algo.