itembuilder - ListView horizontal en Android?
listitem flutter (19)
¿Es posible hacer el ListView
horizontalmente? Lo he hecho Usando la vista de galería, pero el elemento seleccionado aparece automáticamente en el centro de la pantalla. No quiero el elemento seleccionado en el mismo lugar donde hice clic. ¿Cómo puedo rectificar este problema? Mi idea era configurar el ListView
con desplazamiento horizontal. Comparte tu idea?
@Paul responde a una gran solución, pero el código no permite utilizar onClickListeners en elementos secundarios (las funciones de devolución de llamada nunca se llaman). He estado luchando por 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 dispatchTouchEvent
anule onTouchEvent
. Use 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 de los elementos onTouchEvent
y dárselo a nuestro onTouchEvent
, o deje 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 olvides declarar las variables en tu clase:
private float mInitialX;
private float mInitialY;
Bueno, siempre puede crear sus vistas de texto, etc. de forma dinámica y configurar sus onclick listeners como lo haría con un adaptador.
Descarga el archivo jar desde here
ahora póngalo en su carpeta libs, haga clic derecho y seleccione ''Agregar como biblioteca''
Ahora en main.xml pon este código
<com.devsmart.android.ui.HorizontalListView
android:id="@+id/hlistview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Ahora, en la clase de actividad, si desea una vista de lista horizontal con imágenes, coloque 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;
}
Desde que Google introdujo la biblioteca de soporte de Android v7 21.0.0, puede utilizar RecyclerView para desplazar los elementos horizontalmente. El widget RecyclerView es una versión más avanzada y flexible de ListView.
Para usar RecyclerView, solo agregue 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 sobre RecyclerView:
Esto es un poco (muy) tarde, pero lo estoy publicando en caso de que alguien llegue más tarde.
La biblioteca de soporte a partir de la vista previa de Android L tiene un RecyclerView
que hace exactamente lo que quiere.
En este momento, solo puede obtenerlo a través del SDK de previsualización de 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 here .
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);
Esto no es una gran respuesta, pero ¿qué hay de usar una vista de desplazamiento horizontal ?
Hay una gran biblioteca para eso, llamada TwoWayView , es muy fácil de implementar, solo incluye la biblioteca del proyecto en tu espacio de trabajo y agrégala como un proyecto de biblioteca a tu proyecto original, y luego sigue 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):
<style name="TwoWayView">
<item name="android:orientation">horizontal</item>
</style>
Entonces,
En su XML de diseño, use el siguiente código para agregar TwoWayView:
<org.lucasr.twowayview.TwoWayView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/lvItems"
style="@style/TwoWayView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"
tools:context=".MainActivity" />
y finalmente, simplemente declárelo y trátelo 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 configura el modo de elección, el método setChoiceMode
no toma un valor int
, sino un valor de enum
llamado ChoiceMode
, por list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
tanto list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
será lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE
lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE
.
He desarrollado una lógica para hacerlo sin usar ninguna biblioteca externa de scrollview horizontal, aquí está la vista horizontal que obtuve y publiqué mi respuesta aquí: https://.com/a/33301582/5479863
Mi respuesta de 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"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="5">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4" />
<HorizontalScrollView
android:id="@+id/horizontalScroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
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á funcionando aquí es el ID que le asigné a ImageView "imgView.setId (v)" y después de aplicar OnClickListener, vuelvo a buscar el ID de la vista ... También he comentado dentro del código, así que que es fácil de entender, espero que esto pueda ser muy útil ... Happy Coding ... :)
He hecho un montón de búsqueda de 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 desde cero extendiendo AdapterView
. Es bastante miserable Vea mi pregunta de SO sobre ListViews horizontal .
HorizontialListView no puede funcionar cuando los datos en el adaptador están involucrados en otro hilo. Todo funciona al 100% en el hilo de la interfaz de usuario. Este es un gran problema en los subprocesos múltiples. Creo que usar HorizontialListView no es la mejor solución para su problema. HorzListView es una mejor manera. Simplemente reemplace su Galería anterior con HorzListView. No necesita modificar el código sobre el adaptador. Entonces todo va como espera. Vea https://.com/a/12339708/1525777 sobre HorzListView.
Mi solución es simplemente usar el widget ViewPager
. No está bloqueado en el centro como Gallery
y tiene funciones integradas para el reciclaje de vistas (como ListView
). Puede ver un enfoque similar en la aplicación Google Play, siempre que trabaje con listas desplazables horizontalmente.
Solo necesitas 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ás un widget desplazable horizontalmente con adaptador, como este:
Para mi aplicación, uso un HorizontalScrollView que contiene LinearLayout dentro, que tiene la orientación establecida en horizontal. Para agregar imágenes dentro, creo ImageViews dentro de la actividad y las agrego a mi LinearLayout. Por ejemplo:
<HorizontalScrollView
android:id="@+id/photo_scroll"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="horizontal"
android:visibility="gone">
<LinearLayout
android:id="@+id/imageview_holder"
android:layout_width="wrap_content"
android:orientation="horizontal"
android:layout_height="match_parent">
</LinearLayout>
</HorizontalScrollView>
Y esto funciona perfectamente bien para mí. En la actividad, todo lo que tengo que hacer es algo 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.
Paul no se molesta en corregir los errores de su biblioteca o aceptar correcciones de los usuarios. Es por eso que estoy sugiriendo otra biblioteca que tiene una funcionalidad similar:
https://github.com/sephiroth74/HorizontalVariableListView
Actualización : el 24 de julio de 2013, el 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 tuvo la versión anterior y funciona muy bien.
Puede usar ViewFlipper para incluir el diseño XML y agregar imágenes, vista de lista para cada diseño XML
Puedes usar RecyclerView en la biblioteca de soporte. RecyclerView es una versión generalizada de ListView que admite:
- Un gestor de diseño para posicionar elementos.
- Animaciones predeterminadas para operaciones de elementos comunes
Según la Documentación de Android, RecyclerView
es la nueva forma de organizar los elementos en la vista de lista y mostrarlos horizontalmente.
Ventajas:
- Ya que al usar el adaptador Recyclerview, el patrón de ViewHolder se implementa automáticamente
- La animación es fácil de realizar
- Muchas mas caracteristicas
Más información sobre RecyclerView
:
Muestra:
Solo agregue el bloque de abajo para hacer el ListView
a 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);
Tuve que hacer lo mismo para uno de mis proyectos y terminé escribiendo el mío también. Lo llamé HorzListView ahora es parte de mi biblioteca de código abierto Aniqroid .
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
Usé el enlace de vista de lista horizontal en mi proyecto y obtuve buenos resultados. Al principio me habían usado la biblioteca devsmart pero me dio algunos problemas. Así que la mejor manera de usar el enlace de vista de lista horizontal ya 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. Disfrutar :)
En realidad es muy simple : simplemente gire la vista de lista para ponerla 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 de pie:
mylistViewchild.setRotation(90);
Editar: si su ListView no encaja correctamente después de la rotación, coloque el ListView dentro de este RotateLayout así:
<com.github.rongi.rotate_layout.layout.RotateLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:angle="90"> <!-- Specify rotate angle here -->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</com.github.rongi.rotate_layout.layout.RotateLayout>