Saltar al contenido

ListView dentro de ScrollView no se desplaza en Android

Ya no busques más en otros sitios ya que has llegado al sitio necesario, contamos con la solución que quieres recibir sin problemas.

Solución:

Encontré una solución que funciona de manera excelente y puede desplazar el ListView sin problemas:

ListView lv = (ListView)findViewById(R.id.myListView);  // your listview inside scrollview
lv.setOnTouchListener(new ListView.OnTouchListener() 
        @Override
        public boolean onTouch(View v, MotionEvent event) 
            int action = event.getAction();
            switch (action) 
            case MotionEvent.ACTION_DOWN:
                // Disallow ScrollView to intercept touch events.
                v.getParent().requestDisallowInterceptTouchEvent(true);
                break;

            case MotionEvent.ACTION_UP:
                // Allow ScrollView to intercept touch events.
                v.getParent().requestDisallowInterceptTouchEvent(false);
                break;
            

            // Handle ListView touch events.
            v.onTouchEvent(event);
            return true;
        
    );

Lo que esto hace es deshabilitar el TouchEvents en el ScrollView y hacer el ListView interceptarlos. Es simple y funciona todo el tiempo.

No deberías poner un ListView dentro de una ScrollView porque el ListView la clase implementa su propio desplazamiento y simplemente no recibe gestos porque todos son manejados por el padre ScrollView. Le recomiendo encarecidamente que simplifique su diseño de alguna manera. Por ejemplo, puede agregar las vistas que desea que se desplacen a la ListView como encabezados o pies de página.

ACTUALIZAR:

A partir de API nivel 21 (Lollipop), los contenedores de desplazamiento anidados son oficialmente compatibles con el SDK de Android. Hay un montón de métodos en View y ViewGroup clases que proporcionan esta funcionalidad. Para que el desplazamiento anidado funcione en Lollipop, debe habilitarlo para una vista de desplazamiento infantil agregando android:nestedScrollingEnabled="true" a su declaración XML o llamando explícitamente setNestedScrollingEnabled(true).

Si desea que el desplazamiento anidado funcione en dispositivos anteriores a Lollipop, lo que probablemente haga, debe usar las clases de utilidad correspondientes de la biblioteca de soporte. Primero tienes que reemplazarte ScrollView con NestedScrollView. Este último implementa tanto NestedScrollingParent como NestedScrollingChild para que pueda usarse como contenedor de desplazamiento principal o secundario.

Pero ListView no admite el desplazamiento anidado, por lo tanto, debe subclasificarlo e implementarlo NestedScrollingChild. Afortunadamente, la biblioteca de soporte proporciona la clase NestedScrollingChildHelper, por lo que solo tiene que crear una instancia de esta clase y llamar a sus métodos desde los métodos correspondientes de su clase de vista.

También tengo una solución. Yo siempre utilizo este método. Prueba esto




        

            
            
        

        

            
            
        


Clase NestedListView.java:

public class NestedListView extends ListView implements OnTouchListener, OnScrollListener 

    private int listViewTouchAction;
    private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

    public NestedListView(Context context, AttributeSet attrs) 
        super(context, attrs);
        listViewTouchAction = -1;
        setOnScrollListener(this);
        setOnTouchListener(this);
    

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) 
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) 
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) 
                scrollBy(0, -1);
            
        
    

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) 
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int newHeight = 0;
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) 
            ListAdapter listAdapter = getAdapter();
            if (listAdapter != null && !listAdapter.isEmpty()) 
                int listPosition = 0;
                for (listPosition = 0; listPosition < listAdapter.getCount()
                        && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) 
                    View listItem = listAdapter.getView(listPosition, null, this);
                    //now it will not throw a NPE if listItem is a ViewGroup instance
                    if (listItem instanceof ViewGroup) 
                        listItem.setLayoutParams(new LayoutParams(
                                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                    
                    listItem.measure(widthMeasureSpec, heightMeasureSpec);
                    newHeight += listItem.getMeasuredHeight();
                
                newHeight += getDividerHeight() * listPosition;
            
            if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) 
                if (newHeight > heightSize) 
                    newHeight = heightSize;
                
            
         else 
            newHeight = getMeasuredHeight();
        
        setMeasuredDimension(getMeasuredWidth(), newHeight);
    

    @Override
    public boolean onTouch(View v, MotionEvent event) 
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) 
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) 
                scrollBy(0, 1);
            
        
        return false;
    

Puedes asentar nuestra misión exponiendo un comentario y puntuándolo te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *