studio programacion para herramientas fundamentos desarrollo con avanzado aplicaciones android listview scrollview motionevent

android - programacion - Pase el evento de movimiento al principal Vista de desplazamiento cuando Lista vista en la parte superior/inferior



manual android studio avanzado (3)

No debe poner ListView dentro de ScrollView, pero puede lograr su requerimiento usando ExpandibleHeightListView . Esto hará que Listview de altura completa dentro de ScrollView. No es necesario agregar TouchListener.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <!-- your content --> </RelativeLayout> <my.widget.ExpandableHeightListView android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView>

Y otra forma de lograr su requisito es RecyclerView con encabezado.

Tengo un ListView en ScrollView para mostrar comentarios y me gustaría hacer lo siguiente:

Cuando el usuario se desliza hacia abajo, primero ScrollView debe ScrollView hacia abajo, ya que la lista está en la parte inferior. Una vez que esté completamente inactivo, Listiew debería comenzar a desplazarse.

De manera similar, cuando el usuario se desplaza hacia arriba, primero ListView (¡orden invertida aquí!) Debe desplazarse hacia arriba, antes de que ScrollView comience a desplazarse.

Hasta ahora he hecho lo siguiente:

listView.setOnTouchListener(new View.OnTouchListener() { // Setting on Touch Listener for handling the touch inside ScrollView @Override public boolean onTouch(View v, MotionEvent event) { // If going up but the list is already at up, return false indicating we did not consume it. if(event.getAction() == MotionEvent.ACTION_UP) { if (listView.getChildCount() == 0 && listView.getChildAt(0).getTop() == 0) { Log.e("Listview", "At top!"); return false; } } // Similar behaviour but when going down check if we are at the bottom. if( event.getAction() == MotionEvent.ACTION_DOWN) { if (listView.getLastVisiblePosition() == listView.getAdapter().getCount() - 1 && listView.getChildAt(listView.getChildCount() - 1).getBottom() <= listView.getHeight()) { Log.e("Listview","At bottom!"); v.getParent().requestDisallowInterceptTouchEvent(false); return false; } } v.getParent().requestDisallowInterceptTouchEvent(true); return false; } });

Los registros se disparan en el momento correcto, sin embargo, el ScrollView no se moverá a pesar de que devuelvo falso.

También intenté agregar v.getParent().requestDisallowInterceptTouchEvent(false); a las declaraciones, pero eso tampoco funcionó.

¿Cómo puedo hacer que funcione?


Prueba esto:

  1. Primero encuentra si alcanzaste en scrollview Bottom. Registre onScrollChanged en su vista de desplazamiento

    @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { // Grab the last child placed in the ScrollView, we need it to determinate the bottom position. View view = (View) getChildAt(getChildCount()-1); // Calculate the scrolldiff int diff = (view.getBottom()-(getHeight()+getScrollY())); // if diff is zero, then the bottom has been reached if( diff == 0 ) { // notify that we have reached the bottom // Add code here to start scrolling the ListView Log.d(ScrollTest.LOG_TAG, "MyScrollView: Bottom has been reached" ); } super.onScrollChanged(l, t, oldl, oldt); }

  2. Compruebe si llega a la parte superior de ListView. Compruebe si firstVisibleItem es 0: -

    tableListView.setOnScrollListener(new OnScrollListener() { public void onScrollStateChanged(AbsListView view, int scrollState) { } public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (visibleItemCount == 0) // you have reached at top of lustView { java.lang.System.out.println("you have reached at top of lustView!"); } else { if ((firstVisibleItem + visibleItemCount) == totalItemCount) { // put your stuff here java.lang.System.out.println("end of the line reached!"); } } } });

Espero que esto funcione para ti. Si enfrenta algún problema, hágamelo saber.


Puede crear un ScrollView personalizado y ListView y anular

onInterceptTouchEvent(MotionEvent event)

Me gusta esto:

@Override public boolean onInterceptTouchEvent(MotionEvent event) { View view = (View) getChildAt(getChildCount()-1); int diff = (view.getBottom()-(getHeight()+getScrollY())); if( event.getAction() == MotionEvent.ACTION_DOWN) { if (diff ==0) { return false; } } return super.onInterceptTouchEvent(event); }

De esta forma, cada Abajo Toque en el ListView mientras se encuentra en la parte inferior de ScrollView irá a ListView .

Esta es solo una implementación de boceto, pero creo que podría comenzar con esto haciendo lo mismo para detectar cuando se encuentra en la parte superior de ListView

Como nota, probaría una implementación más sencilla usando solo ListView con el contenido actual de ScrollView agregado como encabezado de ListView usando listView.addHeaderView(scrollViewContent) . No sé si esto se adapta a tus necesidades.

EDITAR:

Detectando cuándo debería comenzar a desplazarse por ScrollView . Mantener una referencia de ListView en ScrollView . Cuando el usuario se desplaza hacia arriba y el ListView está en la parte superior, el ScrollView consume el evento.

private void init(){ ViewConfiguration vc = ViewConfiguration.get(getContext()); mTouchSlop = vc.getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { final int action = MotionEventCompat.getActionMasked(event); switch (action) { case MotionEvent.ACTION_DOWN:{ yPrec = event.getY(); } case MotionEvent.ACTION_MOVE: { final float dy = event.getY() - yPrec; if (dy > mTouchSlop) { // Start scrolling! mIsScrolling = true; } break; } } if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mIsScrolling = false; } // Calculate the scrolldiff View view = (View) getChildAt(getChildCount()-1); int diff = (view.getBottom()-(getHeight()+getScrollY())); if ((!mIsScrolling || !listViewReference.listIsAtTop()) && diff == 0) { if (event.getAction() == MotionEvent.ACTION_MOVE) { return false; } } return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mIsScrolling = false; } return super.onTouchEvent(ev); } public void setListViewReference(MyListView listViewReference) { this.listViewReference = listViewReference; }

El método listIsAtTop en ListView se ve así:

public boolean listIsAtTop() { if(getChildCount() == 0) return true; return (getChildAt(0).getTop() == 0 && getFirstVisiblePosition() ==0); }