utilizar studio pantalla linearlayout hacer funciona deslizar como bajar android android-5.0-lollipop android-design-library android-coordinatorlayout

linearlayout - deslizar pantalla android studio



Android: el pie de página se desplaza fuera de la pantalla cuando se usa en CoordinatorLayout (9)

Coordinador de Android Diseño de ejemplo de comportamiento de diseño inferior

activity_bottom.xml

<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/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimaryDark" app:layout_scrollFlags="scroll|enterAlways" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#C0C0C0" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <com.example.android.coordinatedeffort.widget.FooterBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="bottom"> <TextView android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="#007432" android:gravity="center" android:text="Footer View" android:textColor="@android:color/white" android:textSize="25sp" /> </com.example.android.coordinatedeffort.widget.FooterBarLayout> </android.support.design.widget.CoordinatorLayout>

FooterBarLayout.java

FooterBarBehavior.java

Tengo un AppBarLayout que se desplaza fuera de la pantalla al desplazar un RecyclerView . Debajo de RecyclerView hay un RelativeLayout que es un pie de página.

El pie de página se muestra solo después de desplazarse hacia arriba: se comporta como si

layout_scrollFlags="scroll|enterAlways"

pero no tiene ningún indicador de desplazamiento: ¿es un error o estoy haciendo algo mal? Quiero que sea siempre visible

antes de desplazarse

después de desplazarse

Actualizar

abrió un problema de Google sobre esto: estaba marcado como ''WorkingAsIntended'', esto todavía no ayuda porque quiero una solución de trabajo de un pie de página dentro de un fragmento.

Actualización 2

puedes encontrar la actividad y el fragmento xmls aquí -

tenga en cuenta que si la línea 34 en activity.xml - la línea que contiene la app:layout_behavior="@string/appbar_scrolling_view_behavior" está comentada, el final del texto es visible desde el principio; de lo contrario, es visible solo después de desplazarse hacia arriba


Comencé con la solución de Noa ( https://.com/a/31140112/1317564 ) y funcionó para arrastrar los dedos, pero estaba teniendo problemas con las aventuras. Después de pasar un tiempo para rastrear las llamadas al método y probar diferentes ideas, aquí está la solución con la que terminé:

// Workaround for https://code.google.com/p/android/issues/detail?id=177195 // Based off of solution originally found here: https://.com/a/31140112/1317564 @SuppressWarnings("unused") public class CustomScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior { private AppBarLayout appBarLayout; private boolean onAnimationRunnablePosted = false; @SuppressWarnings("unused") public CustomScrollingViewBehavior() { } @SuppressWarnings("unused") public CustomScrollingViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if (appBarLayout != null) { // We need to check from when a scroll is started, as we may not have had the chance to update the layout at // the start of a scroll or fling event. startAnimationRunnable(child, appBarLayout); } return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public boolean onMeasureChild(CoordinatorLayout parent, final View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { if (appBarLayout != null) { final int bottomPadding = calculateBottomPadding(appBarLayout); if (bottomPadding != child.getPaddingBottom()) { // We need to update the padding in onMeasureChild as otherwise we won''t have the correct padding in // place when the view is flung, and the changes done in onDependentViewChanged will only take effect on // the next animation frame, which means it will be out of sync with the new scroll offset. This is only // needed when the view is flung -- when dragged with a finger, things work fine with just // implementing onDependentViewChanged(). child.setPadding(child.getPaddingLeft(), child.getPaddingTop(), child.getPaddingRight(), bottomPadding); } } return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, final View child, final View dependency) { if (appBarLayout == null) appBarLayout = (AppBarLayout) dependency; final boolean result = super.onDependentViewChanged(parent, child, dependency); final int bottomPadding = calculateBottomPadding(appBarLayout); final boolean paddingChanged = bottomPadding != child.getPaddingBottom(); if (paddingChanged) { // If we''ve changed the padding, then update the child and make sure a layout is requested. child.setPadding(child.getPaddingLeft(), child.getPaddingTop(), child.getPaddingRight(), bottomPadding); child.requestLayout(); } // Even if we didn''t change the padding, if onDependentViewChanged was called then that means that the app bar // layout was changed or was flung. In that case, we want to check for these changes over the next few animation // frames so that we can ensure that we capture all the changes and update the view pager padding to match. startAnimationRunnable(child, dependency); return paddingChanged || result; } // Calculate the padding needed to keep the bottom of the view pager''s content at the same location on the screen. private int calculateBottomPadding(AppBarLayout dependency) { final int totalScrollRange = dependency.getTotalScrollRange(); return totalScrollRange + dependency.getTop(); } private void startAnimationRunnable(final View child, final View dependency) { if (onAnimationRunnablePosted) return; final int onPostChildTop = child.getTop(); final int onPostDependencyTop = dependency.getTop(); onAnimationRunnablePosted = true; // Start looking for changes at the beginning of each animation frame. If there are any changes, we have to // ensure that layout is run again so that we can update the padding to take the changes into account. child.postOnAnimation(new Runnable() { private static final int MAX_COUNT_OF_FRAMES_WITH_NO_CHANGES = 5; private int previousChildTop = onPostChildTop; private int previousDependencyTop = onPostDependencyTop; private int countOfFramesWithNoChanges; @Override public void run() { // Make sure we request a layout at the beginning of each animation frame, until we notice a few // frames where nothing changed. final int currentChildTop = child.getTop(); final int currentDependencyTop = dependency.getTop(); boolean hasChanged = false; if (currentChildTop != previousChildTop) { previousChildTop = currentChildTop; hasChanged = true; countOfFramesWithNoChanges = 0; } if (currentDependencyTop != previousDependencyTop) { previousDependencyTop = currentDependencyTop; hasChanged = true; countOfFramesWithNoChanges = 0; } if (!hasChanged) { countOfFramesWithNoChanges++; } if (countOfFramesWithNoChanges <= MAX_COUNT_OF_FRAMES_WITH_NO_CHANGES) { // We can still look for changes on subsequent frames. child.requestLayout(); child.postOnAnimation(this); } else { // We''ve encountered enough frames with no changes. Do a final layout request, and don''t repost. child.requestLayout(); onAnimationRunnablePosted = false; } } }); } }

No soy fanático de volver a verificar el diseño en cada cuadro de animación, y esta solución no es perfecta ya que he visto algunos problemas si expando / colapso programáticamente el diseño de la barra de la aplicación, pero por ahora no he encontrado una solución mejor . El rendimiento es bueno en un dispositivo nuevo y aceptable en un dispositivo antiguo. Si alguien más lo hace, no dude en tomar mi respuesta como fuente y volver a publicarla.


Creo que crear un encabezado y un pie de página fijos podría resolver su problema. Hubiera escrito esto en los comentarios pero no tengo 50 rep. Podrías descubrir cómo hacerlo here


Hay una biblioteca para su problema. Espero que esto realmente te ayude. Aquí está la biblioteca

Y otro problema que ha mencionado solucionó el pie de página. el siguiente es el diseño relativo, así que use la función android:layout_alignParentBottom="true" en su pie de página.

Espero que haya resuelto el problema


Hice algo parecido a asegurar que agregué android:layout_gravity="end|bottom" al diseño en XML que quería en la parte inferior de CoordinatorLayout

y luego establecer en el código:

mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @SuppressLint("NewApi") @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { if (mFooterView != null) { final int height = mFooterView.getHeight(); mRecyclerView.setPadding(0, 0, 0, height); mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } });

Nota: que View / ViewGroup de pie de página debe ser más alto en el eje z (enumerado debajo de RecyclerView en XML) para funcionar correctamente


Rodea tus elementos con una distribución lineal, así:

<android.support.design.widget.CoordinatorLayout > <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout> <android.support.v7.widget.Toolbar /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> </LinearLayout> </android.support.design.widget.CoordinatorLayout>


Utilizo una versión simplificada de la solución Learn OpenGL ES ( https://.com/a/33396965/778951 ), que mejora la solución de Noa ( https://.com/a/31140112/1317564 ). Funciona bien para mi barra de herramientas de retorno rápido simple sobre un TabLayout con botones de pie de página en el contenido de ViewPager de cada pestaña.

Simplemente configure FixScrollingFooterBehavior como layout_behavior en View / ViewGroup que desea mantener alineado en la parte inferior de la pantalla.

Diseño:

<?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: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="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:minHeight="?android:attr/actionBarSize" app:title="Foo" app:layout_scrollFlags="scroll|enterAlways|snap" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="com.spreeza.shop.ui.widgets.FixScrollingFooterBehavior" /> </android.support.design.widget.CoordinatorLayout>

Comportamiento:

public class FixScrollingFooterBehavior extends AppBarLayout.ScrollingViewBehavior { private AppBarLayout appBarLayout; public FixScrollingFooterBehavior() { super(); } public FixScrollingFooterBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { if (appBarLayout == null) { appBarLayout = (AppBarLayout) dependency; } final boolean result = super.onDependentViewChanged(parent, child, dependency); final int bottomPadding = calculateBottomPadding(appBarLayout); final boolean paddingChanged = bottomPadding != child.getPaddingBottom(); if (paddingChanged) { child.setPadding( child.getPaddingLeft(), child.getPaddingTop(), child.getPaddingRight(), bottomPadding); child.requestLayout(); } return paddingChanged || result; } // Calculate the padding needed to keep the bottom of the view pager''s content at the same location on the screen. private int calculateBottomPadding(AppBarLayout dependency) { final int totalScrollRange = dependency.getTotalScrollRange(); return totalScrollRange + dependency.getTop(); } }


Actualizar

La solución a continuación no funciona para 5.1, ya que funciona en 5; en lugar de getTop, use getTranslationY en cualquiera de los cálculos que realice.

layout.getTop()-->(int)layout.getTranslationY() appbar.getTop()+toolbar.getHeight()-->(int)(appbar.getTranslationY()+toolbar.getHeight())

Actualización 2 con la nueva biblioteca de soporte - 22.2.1 - no hay diferencias entre las versiones 5.1 y anteriores, solo debe usar getTop e ignorar la actualización anterior en esta respuesta

Solución original Después de mirar en muchas direcciones, la solución es realmente simple: agregue paddingBottom al fragmento y ajústelo a medida que se desplaza la página.

El relleno es necesario para cubrir los cambios en la posición y de la barra de herramientas: el diseño del coordinador mueve toda la página hacia arriba y hacia abajo a medida que la barra de herramientas desaparece y vuelve a aparecer.

Esto se puede lograr extendiendo AppBarLayout.ScrollingViewBehavior y estableciendo esto como el comportamiento del elemento fragmento de la actividad .

Estos son los conceptos básicos del código: funciona para una actividad con solo una barra de herramientas, puede reemplazarlo con appbar.getTop() + toolbar.getHeight() y esto funcionará mejor si su barra de aplicaciones incluye pestañas .

activity.xml

<android.support.design.widget.CoordinatorLayout android:id="@+id/main" 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"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:elevation="3dp" app:elevation="3dp"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways" /> </android.support.design.widget.AppBarLayout> <fragment android:id="@+id/fragment" android:name="com.example.noa.footer2.MainActivityFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="com.example.noa.footer2.MyBehavior" tools:layout="@layout/fragment"/> </android.support.design.widget.CoordinatorLayout>

fragment.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="48dp" android:background="@android:color/holo_green_dark" tools:context=".MainActivityFragment"> <android.support.v7.widget.RecyclerView android:id="@+id/list" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null"/> <View android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentBottom="true" android:background="@android:color/holo_red_light"/> </RelativeLayout>

MainActivityFragment # onActivityCreated

public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); CoordinatorLayout.LayoutParams lp = (LayoutParams) getView().getLayoutParams(); MyBehavior behavior = (MyBehavior) lp.getBehavior(); behavior.setLayout(getView()); }

Mi comportamiento

public class MyBehavior extends AppBarLayout.ScrollingViewBehavior { private View layout; public MyBehavior() { } public MyBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { boolean result = super.onDependentViewChanged(parent, child, dependency); if (layout != null) { layout.setPadding(layout.getPaddingLeft(), layout.getPaddingTop(), layout .getPaddingRight(), layout.getTop()); } return result; } public void setLayout(View layout) { this.layout = layout; } }


package pl.mkaras.utils; import android.content.Context; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.ViewCompat; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import java.util.List; public class ScrollViewBehaviorFix extends AppBarLayout.ScrollingViewBehavior { public ScrollViewBehaviorFix() { super(); } public ScrollViewBehaviorFix(Context context, AttributeSet attrs) { super(context, attrs); } public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { if (child.getLayoutParams().height == -1) { List<View> dependencies = parent.getDependencies(child); if (dependencies.isEmpty()) { return false; } final AppBarLayout appBar = findFirstAppBarLayout(dependencies); if (appBar != null && ViewCompat.isLaidOut(appBar)) { int availableHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec); if (availableHeight == 0) { availableHeight = parent.getHeight(); } final int height = availableHeight - appBar.getMeasuredHeight(); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST); parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed); int childContentHeight = getContentHeight(child); if (childContentHeight <= height) { updateToolbar(parent, appBar, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed, false); heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed); return true; } else { updateToolbar(parent, appBar, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed, true); return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } } } return false; } private static int getContentHeight(View view) { if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; int contentHeight = 0; for (int index = 0; index < viewGroup.getChildCount(); ++index) { View child = viewGroup.getChildAt(index); contentHeight += child.getMeasuredHeight(); } return contentHeight; } else { return view.getMeasuredHeight(); } } private static AppBarLayout findFirstAppBarLayout(List<View> views) { int i = 0; for (int z = views.size(); i < z; ++i) { View view = views.get(i); if (view instanceof AppBarLayout) { return (AppBarLayout) view; } } throw new IllegalArgumentException("Missing AppBarLayout in CoordinatorLayout dependencies"); } private void updateToolbar(CoordinatorLayout parent, AppBarLayout appBar, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed, boolean toggle) { toggleToolbarScroll(appBar, toggle); appBar.forceLayout(); parent.onMeasureChild(appBar, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } private void toggleToolbarScroll(AppBarLayout appBar, boolean toggle) { for (int index = 0; index < appBar.getChildCount(); ++index) { View child = appBar.getChildAt(index); if (child instanceof Toolbar) { Toolbar toolbar = (Toolbar) child; AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbar.getLayoutParams(); int scrollFlags = params.getScrollFlags(); if (toggle) { scrollFlags |= AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL; } else { scrollFlags &= ~AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL; } params.setScrollFlags(scrollFlags); } } } }

Básicamente, este comportamiento elimina SCROLL bandera de desplazamiento de AppBarLayout , cuando el contenido de desplazamiento en vista dependiente ( RecyclerView , NestedScrollView ) es menor que la altura de la vista, es decir. cuando no es necesario desplazarse. También anula la vista de desplazamiento de desplazamiento, que normalmente es realizada por AppBarLayout.ScrollingViewBehavior . Funciona bien al agregar pie de página, es decir. , a la vista de desplazamiento o en ViewPager , donde la longitud del contenido puede ser diferente en cada página.