183 votos

¿Cómo puedo hacer una horizontal ListView en Android?

Posibles Duplicados:
Horizontal ListView en Android?

Como muchas cosas en Android, no creo que esto sería un problema difícil, pero ohhh, mira por dónde, estaría equivocado. Y, como muchas cosas en Android, la API no sea razonablemente extensible punto de partida. Que me aspen si voy a rodar mi propia ListView, cuando todo lo que quiero es tomar la cosa y le dé a su lado. \despotricar

Bien, ahora que he terminado echando chispas, vamos a hablar sobre el problema en sí. Lo que necesito es, básicamente, algo exactamente igual al Gallery, pero sin el centro-función de bloqueo. En realidad no necesito ListView's listSelector pero es bueno que tienen. En su mayoría, yo podía hacer lo que quiero con un LinearLayout dentro de un ScrollView, pero necesito el niño ve venir de un ListAdapter y realmente me gustaría tener una vista de reciclaje. Y yo realmente no quiero escribir cualquier diseño de código.

Me asomé en el código fuente de algunas de estas clases...

Galería: parece que podría utilizar la Galería si puedo reemplazar la mayoría de los 'onXyz' métodos, copiar todo su código fuente, pero no llamen scrollIntoSlots(). Pero estoy seguro de que si hago lo que me voy a correr en algún miembro campo que es inaccesible o alguna otra consecuencia imprevista.

AbsSpinner: Desde la mRecycler campo es un paquete-privado dudo que voy a ser capaz de extender esta clase.

AbsListView: parece Que esta clase está pensada para el desplazamiento vertical, por lo que no ayuda allí.

AdapterView: nunca he tenido que extender esta clase directamente. Si me dicen que es fácil de hacer, y que es fácil de rollo de mi propia RecycleBin, voy a ser muy escépticos, pero voy a darle un tiro.

Supongo que yo podría copiar tanto AbsSpinner y Gallery para conseguir lo que quiero... esperemos que esas clases no están usando algún paquete-variable privada no tengo acceso. ¿Y ustedes creo que es una buena práctica? ¿Alguien tiene alguna tutoriales o soluciones de terceros que podrían ponerme en la dirección correcta?

Actualización:
La única solución que he encontrado hasta ahora es hacerlo todo yo. Desde esta pregunta, me han anulado AdapterView e implementado en mi propio "HorizontalListView" a partir de cero. La única manera de anular la Galería del centro-función de bloqueo es para anular el privado scrollIntoSlots método, que creo que sería necesario 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 depender de indocumentados métodos que podrían cambiar.

Swathi EP a continuación me sugirió que le dé la Gallery una OnTouchListener y reemplazar la funcionalidad de desplazamiento. Si no se preocupan por tener fling apoyo en su lista, o si está bien que las opiniones se ajuste a la del centro al final de la aventura de animación, entonces esta va a trabajar para usted! Sin embargo, en el final todavía resulta imposible eliminar la centro-función de bloqueo sin quitar aventura de apoyo. Y me pregunto, ¿qué tipo de lista no aventura?

Así que, por desgracia, esto no funciona para mí. :-( Pero si estás interesado en este enfoque, sigue leyendo...

Yo también tuve que hacer algunas adiciones a Swathi del código de obtener lo que quería. En GestureListener.onTouch, además de delegar en el gesto del detector, también tuve que devolver true para ACTION_UP y ACTION_CANCEL eventos. Que desactivan correctamente el centro-función de bloqueo, pero también movilidad lanzando. Yo era capaz de volver a habilitar la aventura por tener mi propio GestureListener delegado a la Galería onFling método. Si quieres probarlo, entra en tu ApiDemos código de ejemplo y sustituir la Gallery1.java clase 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);
        }
    }

}

48voto

Paul Puntos 1578

Después de leer este post, me han aplicado a mi propia Horizontal listview. Usted puede encontrar: http://www.dev-smart.com/?p=34 quisiera saber si esto ayuda...

12voto

Thira Puntos 678

Has mirado en el uso de un HorizontalScrollView para envolver a su lista de artículos? Que permitirán a cada uno de los elementos de lista para ser desplazable horizontalmente (lo que usted pone en usted, y puede hacer de ellos objetos dinámicos similares a los ListView). Esto funciona bien si sólo después de una sola fila de elementos.

4voto

Reuben Scratton Puntos 22314

Usted sabe, podría ser posible utilizar una ListView con algunos juicioso primordial de dispatchDraw() (para girar el Lienzo de 90 grados), onTouch() (para cambiar la X e y de la MotionEvent coords) y tal vez onMeasure() o lo que sea para engañar en pensar que la y por la x en lugar de x por y...

No tengo idea de si esto realmente funciona pero sería divertido averiguarlo. :)

4voto

Esta podría ser una respuesta tardía, pero se está trabajando para nosotros. Estamos utilizando la misma galería proporcionada por Android, solo que, se ha ajustado el margen izquierdo de tal manera que las pantallas extremo izquierdo es considerado como la Galería del centro. Que realmente ha funcionado bien para nosotros.

3voto

free Puntos 31

He utilizado Pauls (ver su respuesta) Implementación de HorizontalListview y funciona, muchas gracias por compartir!

Me ha cambiado un poco su HorizontalListView Clase (btw. Pablo no es un error tipográfico en el nombre de la clase, su nombre de la clase es "HorizontialListView" en lugar de "HorizontalListView", el "yo" es demasiado) para actualizar niño-vistas al seleccionado.

ACTUALIZACIÓN: Mi código que he publicado aquí estaba equivocado supongo que me metió en problemas con la selección (creo que tiene que ver con la vista de reciclaje), tengo que volver al tablero de dibujo...

ACTUALIZACIÓN 2: Ok Problema resuelto, yo simplemente comentó : "removeNonVisibleItems(dx);" en "onLayout(..)", supongo que esto va a perjudicar el rendimiento, pero desde que estoy usando sólo muy pequeñas Listas que esto no es ningún Problema para mí.

Yo, básicamente, utiliza este tutorial aquí en developerlife y sustituido ListView con Pauls HorizontalListView, y de hacer los cambios para permitir la "permanente" de la selección (un niño que se hace clic sobre los cambios en su apariencia, y cuando se hace clic en nuevo se cambia de nuevo).

Soy un principiante, así que probablemente muchas cosas feas en el código, hágamelo saber si usted necesita más detalles.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X