Horizontal ListView en Android?

¿Es posible hacer ListView horizontalmente? He hecho esto usando la vista de galería, pero el elemento seleccionado llega al centro de la pantalla automáticamente. No quiero el artículo seleccionado en el mismo lugar donde hice clic. ¿Cómo puedo rectificar este problema? Mi idea era establecer ListView con desplazamiento horizontal. Comparte tu idea?

Según la documentación de Android, RecyclerView es la nueva forma de organizar los elementos en la vista de lista y de mostrarse horizontalmente.

Ventajas:

  1. Dado que al usar Recyclerview Adapter, el patrón ViewHolder se implementa automáticamente
  2. La animación es fácil de realizar
  3. Muchas mas funciones

Más información sobre RecyclerView :

  1. grokkingandroid.com
  2. antonioleiva.com

Muestra:

survivingwithandroid.com

Simplemente agregue el bloque de abajo para hacer que ListView horizontal desde vertical

Fragmento de código

 LinearLayoutManager layoutManager= new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL, false); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(layoutManager); 

Paul no se molesta en corregir errores de su biblioteca o aceptar arreglos de usuarios. Es por eso que estoy sugiriendo otra biblioteca que tenga una funcionalidad similar:

https://github.com/sephiroth74/HorizontalVariableListView

Actualización : el 24 de julio de 2013 autor (sephiroth74) lanzó una versión completamente reescrita basada en el código de Android 4.2.2 ListView. ¡Debo decir que no tiene todos los errores que la versión anterior tenía y funciona muy bien!

@Paul responde enlaces a una gran solución, pero el código no permite utilizar onClickListeners en elementos secundarios (nunca se llaman las funciones de callback). He estado luchando durante un tiempo para encontrar una solución y he decidido publicar aquí lo que necesita modificar en ese código (en caso de que alguien lo necesite).

En lugar de anular el reemplazo de dispatchTouchEvent onTouchEvent . Utilice el mismo código de dispatchTouchEvent y elimine el método (puede leer la diferencia entre los dos aquí http://developer.android.com/guide/topics/ui/ui-events.html#EventHandlers )

 @Override public boolean onTouchEvent(MotionEvent event) { boolean handled = mGesture.onTouchEvent(event); return handled; } 

Luego, agregue el siguiente código que decidirá robar el evento del elemento children y dárselo a nuestro onTouchEvent , o dejar que sea manejado por ellos.

 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch( ev.getActionMasked() ){ case MotionEvent.ACTION_DOWN: mInitialX = ev.getX(); mInitialY = ev.getY(); return false; case MotionEvent.ACTION_MOVE: float deltaX = Math.abs(ev.getX() - mInitialX); float deltaY = Math.abs(ev.getY() - mInitialY); return ( deltaX > 5 || deltaY > 5 ); default: return super.onInterceptTouchEvent(ev); } } 

Finalmente, no te olvides de declarar las variables en tu clase:

 private float mInitialX; private float mInitialY; 

Desde que Google presentó Android Support Library v7 21.0.0, puede usar RecyclerView para desplazar los elementos horizontalmente. El widget RecyclerView es una versión más avanzada y flexible de ListView.

Para usar RecyclerView, simplemente agrega la dependencia:

 com.android.support:recyclerview-v7:23.0.1 

Aquí hay una muestra:

 public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(layoutManager); MyAdapter adapter = new MyAdapter(myDataset); recyclerView.setAdapter(adapter); } } 

Más información acerca de RecyclerView:

Esto es un poco (muy) tarde, pero estoy publicando esto en caso de que alguien lo haga más tarde.

La Biblioteca de soporte a partir de la vista previa de Android L tiene un RecyclerView que hace exactamente lo que desea.

En este momento, solo puede obtenerlo a través del SDK de vista previa L y necesita configurar su minSdk a L Pero puede copiar todos los archivos necesarios en su proyecto y usarlos de esa manera hasta que L esté oficialmente fuera.

Puede descargar los documentos de vista previa aquí .

Advertencia: La API para la Vista de Reciclador puede cambiar y puede tener errores.

Actualizado

El código fuente para la vista de lista horizontal es:

 LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); RecyclerView myList = findViewById(R.id.my_recycler_view); myList.setLayoutManager(layoutManager); 

Descargue el archivo jar desde aquí

ahora póngalo en su carpeta de libs, haga clic derecho y seleccione ‘Agregar como biblioteca’

ahora en main.xml pon este código

   

ahora en la clase de actividad si quieres vista de lista horizontal con imágenes, coloca este código

  HorizontalListView hListView = (HorizontalListView) findViewById(R.id.hlistview); hListView.setAdapter(new HAdapter(this)); private class HAdapter extends BaseAdapter { LayoutInflater inflater; public HAdapter(Context context) { inflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return Const.template.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { HViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.listinflate, null); holder = new HViewHolder(); convertView.setTag(holder); } else { holder = (HViewHolder) convertView.getTag(); } holder.img = (ImageView) convertView.findViewById(R.id.image); holder.img.setImageResource(Const.template[position]); return convertView; } } class HViewHolder { ImageView img; } 

Es realmente muy simple : simplemente Gire la vista de lista para colocarla de lado

mlistView.setRotation(-90);

Luego al inflar a los niños, eso debería estar dentro del método getView. Gira a los niños para que se pongan derechos:

  mylistViewchild.setRotation(90); 

Editar: si su ListView no se ajusta correctamente después de la rotación, coloque el ListView dentro de este RotateLayout de la siguiente manera:

       

Mi solución es simplemente usar el widget ViewPager . No está bloqueada en el centro como Gallery y tiene funciones integradas para reciclar vistas (como ListView ). Puede ver un enfoque similar en la aplicación Google Play, siempre que trabaje con listas desplazables horizontalmente.

Solo necesita extender PagerAdapter y realizar un par de ajustes allí:

 public class MyPagerAdapter extends PagerAdapter { private Context mContext; public MyPagerAdapter(Context context) { this.mContext = context; } // As per docs, you may use views as key objects directly // if they aren't too complex @Override public Object instantiateItem(ViewGroup container, int position) { LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.item, null); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return 10; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } // Important: page takes all available width by default, // so let's override this method to fit 5 pages within single screen @Override public float getPageWidth(int position) { return 0.2f; } } 

Como resultado, tendrá un widget desplazable horizontalmente con adaptador, como este: enter image description here

Desarrollé una lógica para hacerlo sin usar ninguna biblioteca externa de desplazamiento horizontal, aquí está la vista horizontal que obtuve y he publicado mi respuesta aquí: https://stackoverflow.com/a/33301582/5479863

Mi respuesta json es esta:

 {"searchInfo":{"status":"1","message":"Success","clist":[{"id":"1de57434-795e-49ac-0ca3-5614dacecbd4","name":"Theater","image_url":"http://52.25.198.71/miisecretory/category_images/movie.png"},{"id":"62fe1c92-2192-2ebb-7e92-5614dacad69b","name":"CNG","image_url":"http://52.25.198.71/miisecretory/category_images/cng.png"},{"id":"8060094c-df4f-5290-7983-5614dad31677","name":"Wine-shop","image_url":"http://52.25.198.71/miisecretory/category_images/beer.png"},{"id":"888a90c4-a6b0-c2e2-6b3c-561788e973f6","name":"Chemist","image_url":"http://52.25.198.71/miisecretory/category_images/chemist.png"},{"id":"a39b4ec1-943f-b800-a671-561789a57871","name":"Food","image_url":"http://52.25.198.71/miisecretory/category_images/food.png"},{"id":"c644cc53-2fce-8cbe-0715-5614da9c765f","name":"College","image_url":"http://52.25.198.71/miisecretory/category_images/college.png"},{"id":"c71e8757-072b-1bf4-5b25-5614d980ef15","name":"Hospital","image_url":"http://52.25.198.71/miisecretory/category_images/hospital.png"},{"id":"db835491-d1d2-5467-a1a1-5614d9963c94","name":"Petrol-Pumps","image_url":"http://52.25.198.71/miisecretory/category_images/petrol.png"},{"id":"f13100ca-4052-c0f4-863a-5614d9631afb","name":"ATM","image_url":"http://52.25.198.71/miisecretory/category_images/atm.png"}]}} 

Archivo de diseño:

  < ?xml version="1.0" encoding="utf-8"?>        

archivo de clase:

 LinearLayout linearLayout = (LinearLayout) findViewById(R.id.ll); for (int v = 0; v < collectionInfo.size(); v++) { /*---------------Creating frame layout----------------------*/ FrameLayout frameLayout = new FrameLayout(ActivityMap.this); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, getPixelsToDP(90)); layoutParams.rightMargin = getPixelsToDP(10); frameLayout.setLayoutParams(layoutParams); /*--------------end of frame layout----------------------------*/ /*---------------Creating image view----------------------*/ final ImageView imgView = new ImageView(ActivityMap.this); //create imageview dynamically LinearLayout.LayoutParams lpImage = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); imgView.setImageBitmap(collectionInfo.get(v).getCatImage()); imgView.setLayoutParams(lpImage); // setting ID to retrieve at later time (same as its position) imgView.setId(v); imgView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // getting id which is same as its position Log.i(TAG, "Clicked on " + collectionInfo.get(v.getId()).getCatName()); // getting selected category's data list new GetSelectedCategoryData().execute(collectionInfo.get(v.getId()).getCatID()); } }); /*--------------end of image view----------------------------*/ /*---------------Creating Text view----------------------*/ TextView textView = new TextView(ActivityMap.this);//create textview dynamically textView.setText(collectionInfo.get(v).getCatName()); FrameLayout.LayoutParams lpText = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER); // Note: LinearLayout.LayoutParams 's gravity was not working so I putted Framelayout as 3 paramater is gravity itself textView.setTextColor(Color.parseColor("#43A047")); textView.setLayoutParams(lpText); /*--------------end of Text view----------------------------*/ //Adding views at appropriate places frameLayout.addView(imgView); frameLayout.addView(textView); linearLayout.addView(frameLayout); } private int getPixelsToDP(int dp) { float scale = getResources().getDisplayMetrics().density; int pixels = (int) (dp * scale + 0.5f); return pixels; } 

El truco que está trabajando aquí es la identificación que he asignado a ImageView "imgView.setId (v)" y luego de aplicar onClickListener a eso estoy de nuevo obteniendo el ID de la vista .... También he comentado dentro del código que es fácil de entender, espero que esto sea muy útil ... Happy Coding ... 🙂

http://i.stack.imgur.com/lXrpG.png

Puede usar RecyclerView en la biblioteca de soporte. RecyclerView es una versión generalizada de ListView que admite:

  • Un administrador de diseño para posicionar elementos
  • Animaciones predeterminadas para operaciones de elementos comunes

Documentos de Android Recycler View

Esto no es una gran respuesta, pero ¿qué tal si usamos una vista de desplazamiento horizontal ?

He buscado mucho para encontrar una solución a este problema. La respuesta corta es que no hay una buena solución, sin anular los métodos privados y ese tipo de cosas. Lo mejor que encontré fue implementarlo yo mismo desde cero al extender AdapterView . Es bastante miserable. Vea mi pregunta ASÍ sobre ListViews horizontales .

Tuve que hacer lo mismo para uno de mis proyectos y también terminé escribiendo el mío. Lo llamé HorzListView ahora es parte de mi biblioteca Aniqroid de fuente abierta.

http://aniqroid.sileria.com/doc/api/ (busque descargas en la parte inferior o use el proyecto de código de google para ver más opciones de descarga: http://code.google.com/p/aniqroid/downloads/list )

La documentación de la clase está aquí: http://aniqroid.sileria.com/doc/api/com/sileria/android/view/HorzListView.html

Para mi aplicación, uso un HorizontalScrollView que contiene LinearLayout en el interior, que tiene la orientación establecida en horizontal. Para agregar imágenes adentro, creo ImageViews dentro de la actividad y los agrego a LinearLayout. Por ejemplo:

     

Y esto funciona perfectamente bien para mí. En la actividad, todo lo que tengo que hacer es algo así como el siguiente código:

 LinearLayout imgViewHolder = findViewById(R.id.imageview_holder); ImageView img1 = new ImageView(getApplicationContext()); //set bitmap //set img1 layout params imgViewHolder.add(img1); ImageView img2 = new ImageView(getApplicationContext()); //set bitmap //set img2 layout params imgViewHolder.add(img2); 

Como dije, eso funciona para mí, y espero que ayude a alguien que busque lograr esto también.

bueno, siempre puedes crear tus textviews, etc. dinámicamente y configurar tus clics onclick como lo harías con un adaptador

HorizontialListView no puede funcionar cuando los datos en el adaptador están involucrados en otro hilo. Todo funciona al 100% en el hilo de UI. Este es un gran problema en multihilo. Creo que el uso de HorizontialListView no es la mejor solución para su problema.HorzListView es una mejor manera. Simplemente reemplaza su galería anterior con HorzListView. No necesita modificar el código sobre el adaptador. Luego todo va como usted espera. Vea https: // stackoverflow.com/a/12339708/1525777 sobre HorzListView.

Utilicé el enlace de la lista horizontal en mi proyecto y obtuve buenos resultados. Me habían utilizado la biblioteca devsmart inicialmente, pero me dio algunos problemas. Entonces, la mejor forma de usar el enlace de la lista horizontal es que recuperé mis problemas y también recientemente lancé mi aplicación en Google PlayStore usando esta biblioteca y obtuve una buena respuesta de los usuarios. Por lo tanto, le recomiendo que use la misma biblioteca que mencioné anteriormente para mostrar la vista de lista horizontalmente. Disfruta 🙂

Hay una gran biblioteca para eso, llamada TwoWayView , es muy fácil de implementar, simplemente incluya la biblioteca del proyecto en su espacio de trabajo y agréguela como proyecto de biblioteca a su proyecto original, y luego siga los siguientes pasos que se mencionan originalmente aquí :

Primero, agreguemos un estilo que indique la orientación de ListView (horizontal o vertical) en (res / values ​​/ styles.xml):

  

Entonces,

En su diseño XML, use el siguiente código para agregar TwoWayView:

  

y finalmente, simplemente declararlo y lidiar con él como cualquier ListView regular:

 TwoWayView lvTest = (TwoWayView) findViewById(R.id.lvItems); 

Todos los métodos de ListView funcionarán aquí como de costumbre, pero solo noté una diferencia, que es cuando se establece el modo de elección, el método setChoiceMode no toma un valor int sino un valor de enum llamado ChoiceMode , por lo que list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE); será lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE .

Puede usar ViewFlipper para incluir el diseño XML y agregar imágenes, vista de lista para cada diseño XML