Cómo agregar desplazamiento para una vista personalizada en Android

Acabo de empezar a escribir una vista personalizada en Android (por primera vez) y me he dado cuenta de que necesito implementar una función de desplazamiento.

La vista personalizada también utiliza un encabezado que contiene algún texto (que debe permanecer fijo y no desplazarse).

He leído la documentación de GestureDetector.SimpleOnGestureListener y Scroller . También leí la documentación sobre la animación de un gesto Scroll, pero encontré los ejemplos difíciles de entender. También he mirado otras preguntas sobre la pila de desbordamiento que ayudó un poco.

Utilizando lo que entendí de la documentación con la respuesta de desbordamiento de pila como referencia para guiarme, he añadido lo siguiente a mi vista personalizada:

Variables y campos:

 private OverScroller mScroller; private final GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // Note 0 as the x-distance to prevent horizontal scrolling scrollBy(0, (int) distanceY); return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { final int maxScrollX = 0; // wholeViewHeight is height of everything that is drawn int wholeViewHeight = calculateWholeHeight(); int visibleHeight = getHeight(); final int maxScrollY = wholeViewHeight - visibleHeight; mScroller.forceFinished(true); mScroller.fling(0, // No startX as there is no horizontal scrolling getScrollY(), 0, // No velocityX as there is no horizontal scrolling - (int) velocityY, 0, maxScrollX, 0, maxScrollY); invalidate(); return true; } @Override public boolean onDown(MotionEvent e) { if (!mScroller.isFinished()) { mScroller.forceFinished(true); } return true; } }); 

Inicialización de mScroller :

 // Called from the constructor private void init() { mScroller = new OverScroller(getContext(), new FastOutLinearInInterpolator()); ... } 

Cosas en onDraw() :

 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); ... if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); } } 

Cosas en onTouchEvent() :

 @Override public boolean onTouchEvent(MotionEvent event) { return mGestureDetector.onTouchEvent(event); } 

El resultado de estas adiciones es una vista personalizada que puede desplazarse verticalmente (y no horizontalmente), sin embargo hay algunos problemas:

  1. Puedo desplazarme más allá de lo que se dibuja
  2. No hay efecto de brillo de borde al llegar al final de la vista personalizada (me refiero a un RecyclerView o ScrollView )
  3. Todas las vistas personalizadas se desplazan en lugar de sólo una cierta parte de ella
  4. No entiendo completamente lo que está pasando

¿Podría alguien explicar cómo funciona el desplazamiento en una vista personalizada y cómo implementarla correctamente con estas características?

¿Puedo ofrecer un diseño simple que tenga un encabezado fijo y un contenido de desplazamiento vertical que suene como si hiciera lo que quiera y no requiere una programación compleja? Esto puede ahorrarle tener que pasar horas de investigación y programación a largo plazo:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content"/> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:fillViewport="true"> <FrameLayout android:id="@+id/scrolling_content" android:layout_width="match_parent" android:layout_height="wrap_content"/> </android.support.v4.widget.NestedScrollView> </LinearLayout> 

Utilizando este diseño, reemplazar o insertar dentro de FrameLayout con ID "encabezado" con su vista de encabezado fijo. A continuación, pondría su contenido scolling dentro de FrameLayout con el ID "scrolling_content". El NestedScrollingView se situaría directamente debajo de su encabezado fijo y automáticamente le dará el comportamiento de desplazamiento que desea sin ningún código adicional.

  • OnGestureListener # onScroll no se llama desde GestureDetector en Samsung Galaxy Nota 10.1
  • SimpleOnGestureListener nunca entra en el método onFling (...)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.