¿Cómo puedo hacer un ListView horizontal en Android? [duplicar]

Posible duplicado:
ListView horizontal en Android?

Como muchas cosas en Android, no pensarías que esto sería un problema tan difícil, pero oh, por Dios, estarías equivocado. Y, como muchas cosas en Android, la API ni siquiera proporciona un punto de partida razonablemente extensible. Estaré condenado si voy a rodar mi propio ListView, cuando todo lo que quiero es tomar la cosa y ponerla de lado. \despotricar

Bien, ahora que he terminado de fumar, hablemos sobre el problema en sí. Lo que necesito es básicamente algo exactamente comoGallery, pero sin la función de bloqueo central. Realmente no necesitoListView's ListSelector pero es agradable tenerlo. Sobre todo, podría hacer lo que quiera con unLinearLayout dentro de unaScrollView, pero necesito que las vistas secundarias provengan de unListAdapter y realmente me gustaría tener un reciclador de vistas. Y yoDe Verdad No quiero escribir ningún código de diseño.

Eché un vistazo al código fuente de algunas de estas clases ...

Galería: Parece que podría usar la Galería si anulo la mayoría de los métodos 'onXyz', copie todo su código fuente, pero me abstengo de llamarscrollIntoSlots(). Pero estoy seguro de que si lo hago, me encontraré con algún campo miembro que es inaccesible o alguna otra consecuencia imprevista.

AbsSpinner: Desde elmRecycler El campo es un paquete privado. Dudo que pueda extender esta clase.

AbsListView: Parece que esta clase solo está destinada al desplazamiento vertical, por lo que no hay ayuda allí.

Vista de adaptador: Nunca he tenido que extender esta clase directamente. Si me dices que es fácil de hacer, y que es fácil rodar el míoRecycleBin, Seré muy escéptico pero lo intentaré.

Supongo que posiblemente podría copiarambos AbsSpinner yGallery para obtener lo que quiero ... espero que esas clases no estén usando alguna variable de paquete privado a la que no puedo acceder. ¿Ustedes piensan que es una buena práctica? ¿Alguien tiene tutoriales o soluciones de terceros que puedan ponerme en la dirección correcta?

Actualizar:
La única solución que he encontrado hasta ahora es hacerlo todo yo mismo. Desde que hice esta pregunta, he anuladoAdapterView e implementé mi propio "HorizontalListView" desde cero. La única forma de anular verdaderamente la función de bloqueo central de la Galería es anular el privadoscrollIntoSlots método, que creo que requeriría generar una subclase en tiempo de ejecución. Si eres lo suficientemente valiente como para hacer eso, podría decirse que es la mejor solución, pero no quiero confiar en métodos indocumentados que podrían cambiar.

Swathi EP a continuación sugirió que le dé elGallery unOnTouchListener y anular la funcionalidad de desplazamiento. Si no le importa tener soporte de lanzamiento en su lista, o si está bien que las vistas se ajusten al centro al final de la animación de lanzamiento, entonces estoserá ¡trabajo para ti! Sin embargo, al final todavía resulta imposible eliminar la función de bloqueo central sin quitar el soporte de tiro. Y te pregunto, ¿qué tipo de lista no se lanza?

Entonces, por desgracia, esto no funcionó para mí. :-( Pero si estás interesado en este enfoque, sigue leyendo ...

También tuve que hacer algunas adiciones al código de Swathi para obtener lo que quería. EnGestureListener.onTouch, además de delegar en el detector de gestos, también tuve que devolver verdadero paraACTION_UP yACTION_CANCEL eventos. Eso deshabilitó con éxito la función de bloqueo central, pero también deshabilitó el lanzamiento. Pude volver a habilitar el lanzamiento al tener mi propio delegado de GestureListener en la GaleríaonFling método. Si desea probarlo, vaya a su código de muestra ApiDemos y reemplace la clase Gallery1.java con el siguiente código:

import com.example.android.apis.R;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.GestureDetector;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;

public class Gallery1 extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gallery_1);

        // Reference the Gallery view
        final Gallery g = (Gallery) findViewById(R.id.gallery);

        // Set the adapter to our custom adapter (below)
        g.setAdapter(new ImageAdapter(this));

        // Set a item click listener, and just Toast the clicked position
        g.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position, long id) {
                Toast.makeText(Gallery1.this, "" + position, Toast.LENGTH_SHORT).show();
            }
        });

        // Gesture detection
        final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector(g));
        OnTouchListener gestureListener = new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                boolean retVal = gestureDetector.onTouchEvent(event);
                int action = event.getAction();
                if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                    retVal = true;
                    onUp();
                }
                return retVal;
            }

            public void onUp() {
                // Here I am merely copying the Gallery's onUp() method.
                for (int i = g.getChildCount() - 1; i >= 0; i--) {
                    g.getChildAt(i).setPressed(false);
                }
                g.setPressed(false);
            }
        };
        g.setOnTouchListener(gestureListener);

        // We also want to show context menu for longpressed items in the gallery
        registerForContextMenu(g);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        menu.add(R.string.gallery_2_text);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        Toast.makeText(this, "Longpress: " + info.position, Toast.LENGTH_SHORT).show();
        return true;
    }

    public class ImageAdapter extends BaseAdapter {
        int mGalleryItemBackground;

        public ImageAdapter(Context c) {
            mContext = c;
            // See res/values/attrs.xml for the <declare-styleable> that defines
            // Gallery1.
            TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
            mGalleryItemBackground = a.getResourceId(
                    R.styleable.Gallery1_android_galleryItemBackground, 0);
            a.recycle();
        }

        public int getCount() {
            return mImageIds.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView i = new ImageView(mContext);

            i.setImageResource(mImageIds[position]);
            i.setScaleType(ImageView.ScaleType.FIT_XY);
            i.setLayoutParams(new Gallery.LayoutParams(136, 88));

            // The preferred Gallery item background
            i.setBackgroundResource(mGalleryItemBackground);

            return i;
        }

        private Context mContext;

        private Integer[] mImageIds = {
                R.drawable.gallery_photo_1,
                R.drawable.gallery_photo_2,
                R.drawable.gallery_photo_3,
                R.drawable.gallery_photo_4,
                R.drawable.gallery_photo_5,
                R.drawable.gallery_photo_6,
                R.drawable.gallery_photo_7,
                R.drawable.gallery_photo_8
        };
    }

    public class MyGestureDetector extends SimpleOnGestureListener {

        private Gallery gallery;

        public MyGestureDetector(Gallery gallery) {
            this.gallery = gallery;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
                float velocityY) {
            return gallery.onFling(e1, e2, velocityX, velocityY);
        }
    }

}

Respuestas a la pregunta(8)

Su respuesta a la pregunta