¿Cómo implementar NestedScrolling en Android?
Con soporte-v4 biblioteca 22.1.0 android apoya el desplazamiento anidado (pre android 5.0). Desafortunadamente, esta característica no está documentada. Hay dos interfaces ( NestedScrollingParent
y NestedScrollingChild
), así como dos clases de delegado auxiliar ( NestedScrollingChildHelper
y NestedScrollingParentHelper
).
¿Alguien ha trabajado con NestedScrolling en Android?
- Android AppCompat 22.1.1 color de texto predeterminado y estilo ActionMode
- Android: layout_height = "? Attr / actionBarSize" no funciona con soporte: design: 23.0.0 'library
- ClassCastException: android.widget.LinearLayout $ LayoutParams no se puede convertir en com.android.internal.widget.ActionBarOverlayLayout $ LayoutParams
- Android: no puede resolver los temas de appcompat-v7
- Cuadro de diálogo de alerta de Appcompat Fondo del botón de acción En estado presionado
He intentado configurar un pequeño ejemplo, donde utilizo NestedScrollView que implementa tanto NestedScrollingParent
como NestedScrollingChild
.
Mi diseño se ve así:
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <View android:id="@+id/header" android:layout_width="match_parent" android:layout_height="100dp" android:background="#AF1233"/> <android.support.v4.widget.NestedScrollView android:id="@+id/child" android:layout_width="match_parent" android:layout_height="wrap_content" > <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#12AF33" android:text="@string/long_text"/> </FrameLayout> </android.support.v4.widget.NestedScrollView> </LinearLayout> </android.support.v4.widget.NestedScrollView>
Quiero mostrar una header view
y otro NestedScrollView
(id = child) en un NestedScrollView
(id = parent).
La idea era, para ajustar la altura de la vista de desplazamiento secundaria en tiempo de ejecución mediante un OnPredrawListener
:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final NestedScrollView parentScroll = (NestedScrollView) findViewById(R.id.parent); final NestedScrollView nestedScroll = (NestedScrollView) findViewById(R.id.child); parentScroll.setNestedScrollingEnabled(false); final View header = findViewById(R.id.header); parentScroll.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (parentScroll.getHeight() > 0) { parentScroll.getViewTreeObserver().removeOnPreDrawListener(this); nestedScroll.getLayoutParams().height = parentScroll.getHeight() - 40; nestedScroll.setLayoutParams(nestedScroll.getLayoutParams()); nestedScroll.invalidate(); return false; } return true; } }); } }
Por lo tanto, la vista de cabecera se desplaza parcialmente, 40 píxeles se mantendrán visibles desde que establezca la altura de la vista de desplazamiento de niño anidado a parentScroll.getHeight() - 40
. Muy bien, el ajuste de la altura en tiempo de ejecución y el desplazamiento de la vista de desplazamiento principal funciona de la manera esperada (el encabezado se desplaza hacia fuera, 40 píxeles permanecen visibles y el desplazamiento secundario llena el resto de la pantalla debajo del encabezado).
Espero que "NestedScrolling" signifique que puedo hacer un gesto de desplazamiento en cualquier parte de la pantalla (evento táctil capturado por la vista de desplazamiento principal) y si la vista de desplazamiento principal ha llegado al final, la vista de desplazamiento de los nidos anidados comienza a desplazarse. Sin embargo, eso no parece ser el caso (ni para los gestos de desplazamiento simple ni para los gestos de fling).
El evento táctil siempre es manejado por scrollview de niño anidado si el evento táctil comienza en sus límites, de lo contrario por la vista de desplazamiento principal.
¿Es ese el comportamiento esperado de "desplazamiento anidado" o hay una opción para cambiar ese comportamiento?
También intenté reemplazar la vista de desplazamiento secundario anidado con un NestedRecyclerView
. He subclasificado RecyclerView
e implementado NestedScrollingChild
donde delegar todos los métodos a NestedScrollingChildHelper
:
public class NestedRecyclerView extends RecyclerView implements NestedScrollingChild { private final NestedScrollingChildHelper scrollingChildHelper = new NestedScrollingChildHelper(this); public void setNestedScrollingEnabled(boolean enabled) { scrollingChildHelper.setNestedScrollingEnabled(enabled); } public boolean isNestedScrollingEnabled() { return scrollingChildHelper.isNestedScrollingEnabled(); } public boolean startNestedScroll(int axes) { return scrollingChildHelper.startNestedScroll(axes); } public void stopNestedScroll() { scrollingChildHelper.stopNestedScroll(); } public boolean hasNestedScrollingParent() { return scrollingChildHelper.hasNestedScrollingParent(); } public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return scrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return scrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return scrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); } public boolean dispatchNestedPreFling(float velocityX, float velocityY) { return scrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); } }
Pero el NestedRecyclerView
no se desplaza en absoluto. Todos los eventos táctiles son capturados por la vista de desplazamiento principal.
- Utilizar la clase DrawableCompat para aplicar una tintList
- Diferentes estilos de colorControlActivated en Android
- AppCompat v22.1.0 no theming todos los widgets xml correctamente para fragmentos
- Inheriting AppCompat 22.1.1 El cuadro de diálogo colorAccent del tema de la aplicación no funciona
- No se puede convertir en LayerDrawable (después de actualizar v7)
- Necesita utilizar un tema Theme.AppCompat (o descendiente) con esta actividad. Cambiar a Theme.AppCompat causa otro error
- Android: TextView no respeta el androide: TextViewStyle usando appcompat-v7 22.1.1
- Android AppCompat SearchView EditText falta línea inferior en pre-lollipop
Pasé bastante tiempo en esto simplemente pasando por el código android tratando de averiguar qué está pasando en NestedScrollView. Lo siguiente debería funcionar.
public abstract class ParentOfNestedScrollView extends NestedScrollView{ public ParentOfNestedScrollView(Context context, AttributeSet attrs) { super(context, attrs); } /* Have this return the range you want to scroll to until the footer starts scrolling I have it as headerCard.getHeight() on most implementations */ protected abstract int getScrollRange(); /* This has the parent do all the scrolling that happens until you are ready for the child to scroll. */ @Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed){ if (dy > 0 && getScrollY() < getScrollRange()) { int oldScrollY = getScrollY(); scrollBy(0, dy); consumed[1] = getScrollY() - oldScrollY; } } /* Sometimes the parent scroll intercepts the event when you don't want it to. This prevents this from ever happening. */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } }
Parte de mi código fue tomado de esta pregunta . De esto sólo extender esta clase según sea necesario. Mi xml tiene el niño como NestedScrollView como un niño y el padre como este. Esto no maneja flings tan bien como me gustaría, eso es un trabajo en progreso.
- Hacer que Eclipse se comporte como Visual Studio
- WebView carga el sitio web cuando está en línea, carga el archivo local cuando está fuera de línea