android gridview onclicklistener

android - ¿Por qué cambiar los parámetros de diseño establecidos para resolver mi problema "OnClickListener no funciona para el primer elemento en GridView"?



(2)

Estoy usando un GridView para mostrar algunas imágenes y tuve un problema, ya que onClickListener no funcionaba para la primera imagen. Encontré algunas otras preguntas aquí en SO con el mismo problema, pero no me gustan sus "respuestas correctas", ya que la mayoría de ellas tienen el mismo enfoque de:

Básicamente, instanciar la vista cada vez que se llama getview. Esto es horrible para el rendimiento y probablemente enfrentarán problemas de falta de memoria en muchos dispositivos.

En mi caso, muestro en el GridView las imágenes ubicadas dentro de una subcarpeta en la carpeta de activos.

Mi código original con el problema del "primer elemento" (de hecho, mi código original implementó el patrón del usuario, pero este es un poco más simple y enfrenta el mismo problema):

@Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(_activity); } else { imageView = (ImageView) convertView; } // get screen dimensions AssetManager assetManager = _activity.getAssets(); InputStream assetIn = null; try { assetIn = assetManager.open(_assets_subdir + File.separator + _filePaths.get(position)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } Bitmap image = BitmapFactory.decodeStream(assetIn); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth)); imageView.setImageBitmap(image); // image view click listener imageView.setOnClickListener(new OnImageClickListener(position)); return imageView; }

Mi último código para resolver el problema:

@Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(_activity); imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth)); } else { imageView = (ImageView) convertView; } // get screen dimensions AssetManager assetManager = _activity.getAssets(); InputStream assetIn = null; try { assetIn = assetManager.open(_assets_subdir + File.separator + _filePaths.get(position)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } Bitmap image = BitmapFactory.decodeStream(assetIn); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setImageBitmap(image); // image view click listener imageView.setOnClickListener(new OnImageClickListener(position)); return imageView; }

El problema se resolvió moviendo el código imageView.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth)); .

¿Pero por qué? No estoy seguro.

Leí en algún lugar (en SO) que podría estar pasando porque intento acceder a una vista que aún no se ha inflado, y el usuario me recomendó usar getViewTreeObserver() , pero probé ese enfoque y no pude solucionar el problema.

Entonces, decidí probar y error el código para ver dónde se podía encontrar el cuello de botella y encontrar la solución dada.

¿Alguien sabe por qué esto resuelve el problema?


¿Solo tienes un ImageView en tu GridView ? ¿Por qué no usas setOnItemClickListener lugar de OnItemClickListener ?

De esta manera, en tu Activity :

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... gridView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // here you have what you want ... } }); }


GridView se extiende desde AbsListView -> GridView.LayoutParams es en realidad AbsListView.LayoutParams, que incluye algunos datos de estado sobre el tipo de vista y si se recicla o no.

Al inicializar un nuevo conjunto de parámetros de diseño cada vez que se llama a getView (y no solo cuando la vista se crea de nuevo), estaba perdiendo estos datos de estado.

No estoy (actualmente) seguro de por qué solo estaba causando un problema para el primer elemento en la grilla.