Items inside GridView getting repeated when screen scrolls
Solution 1
It's normal that you see the same items as you scroll down the GridView
because in the getView
method you set the drawables for the ImageView
only when the convertView
is null
(for example for the first elements that are seen when the GridView
appear on the screen). If the convertView
is not null
, meaning you have a recycled row view, you don't set the correct image and you remain with the image that was previously set on this recycled view. Try to modify the getView
method like this:
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) { // if it's not recycled, initialize some attributes
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
v = inflater.inflate(R.layout.gridview_item_layout, parent, false);
} else {
v = (View) convertView;
}
TextView text = (TextView)v.findViewById(R.id.grid_item_text);
text.setText(mTextIds[position]);
ImageView image = (ImageView)v.findViewById(R.id.grid_item_image);
image.setImageDrawable(mThumbIds[position]);
return v;
}
Clicking an element shows you the correct items because you use the position
parameter to retrieve the data.
Solution 2
These is my code for GirdView with Button + Textview
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.grid_item, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
TextView text = (TextView)convertView.findViewById(R.id.texto_grid);
text.setText(app_listaActiva_NOMBRES[position]);
Button image = (Button)convertView.findViewById(R.id.miniatura_grid);
image.setBackgroundResource(R.drawable.custom_button);
image.setOnClickListener(new MyOnClickListener2(position,app_listaActiva_SONIDOS));
return convertView;
}
Lucas Jota
Updated on July 09, 2022Comments
-
Lucas Jota almost 2 years
I'm using a GridView to show a set of Categories that user can chose. Each item of the grid is consisted by an ImageView and a TextView, both retrieved from server. When an item is touched, another activity is started.
I thought everything was going right, until I've noticed that some itens were getting repeated when I scrolls the screen. Whenever I scroll down trough the grid, and then back, itens change itś position and get duplicated. But even when I touch the messed up itens, the right values are send to the next activity.
Looking in LogCat, any repeated request to server occurs. In fact, I've got this while scrolling:
06-28 12:36:38.554: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 2061 objects / 156024 bytes in 51ms 06-28 12:36:42.915: D/dalvikvm(358): GC_FOR_MALLOC freed 6590 objects / 737528 bytes in 57ms 06-28 12:38:26.725: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 5426 objects / 468176 bytes in 71ms 06-28 12:38:26.875: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 409 objects / 17480 bytes in 68ms
Looks like everytime I scroll, itens get redraw...
UPDATE: It only redraw itens on the first time I scroll down the GridView. After this, all itens, including repeated ones, keeps on its places.
My java class:
public void proccess(){ int qtdCategorias = json.length(); imagens = new Drawable[qtdCategorias]; categorias = new String[qtdCategorias]; for (int i=0; i<qtdCategorias; i++){ JSONArray c = json.optJSONArray(i); String urlAmigavel = null; String imagemSite = null; String nomeCategoria = null; try { urlAmigavel = c.getString(6); imagemSite = c.getString(3); nomeCategoria = c.getString(2); } catch (JSONException e) { Log.e("CategoriasJogarActivity", e.toString()); e.printStackTrace(); } categorias[i] = nomeCategoria; imagens[i] = getImagem(urlAmigavel, imagemSite); } gridview = (GridView) findViewById(R.id.include3); ImageAdapter imageAdapter = new ImageAdapter(ctx, imagens, categorias); gridview.setAdapter(imageAdapter); gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { String name = null; String idt = null; try { JSONArray c = json.optJSONArray(position); name = c.getString(2); idt = c.getString(0); } catch (JSONException e) { Log.e("CategoriasJogarActivity", "JSONException" + e.toString()); } Intent in = new Intent(getApplicationContext(), JogarActivity.class); in.putExtra(TAG_NAME, name); in.putExtra(TAG_ID, idt); in.putExtra(TAG_PRIMEIRAPERGUNTA, true); startActivity(in); } }); } public Drawable getImagem(String urlAmigavel, String img) { String url = "http://www.qranio.com/pergunta/" + urlAmigavel + "/"+ img; InputStream is = null; try { URL urlImagem = new URL(url); is = (InputStream) getObjeto(urlImagem); } catch (MalformedURLException e1) { Log.e("CategoriasJogarActivity", e1.toString()); e1.printStackTrace(); } Drawable d = Drawable.createFromStream(is, "src"); return d; } private Object getObjeto(URL url) { Object content = null; try { content = url.getContent(); } catch (IOException e) { Log.e("CategoriasJogarActivity", e.toString()); e.printStackTrace(); } return content; }
imageAdapter class
public class ImageAdapter extends BaseAdapter{ private Context mContext; private final Drawable[] mThumbIds; private final String[] mTextIds; public ImageAdapter(Context c, Drawable[] d, String[] s) { mContext = c; mThumbIds = d; mTextIds = s; } public int getCount() { return mThumbIds.length; } public Object getItem(int position) { return null; } public long getItemId(int position) { return 0; } //create a new ImageView for each item referenced by the Adapter public View getView(int position, View convertView, ViewGroup parent) { //ImageView imageView; View v; if (convertView == null) { // if it's not recycled, initialize some attributes LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE ); v = inflater.inflate(R.layout.gridview_item_layout, null); TextView text = (TextView)v.findViewById(R.id.grid_item_text); text.setText(mTextIds[position]); ImageView image = (ImageView)v.findViewById(R.id.grid_item_image); image.setImageDrawable(mThumbIds[position]); } else { v = (View) convertView; } return v; } }
gridview_item_layout xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview_item_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center_horizontal" > <ImageView android:id="@+id/grid_item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" android:minHeight="100dip" android:minWidth="100dip" > </ImageView> <TextView android:id="@+id/grid_item_text" android:layout_width="match_parent" android:layout_height="match_parent" android:text="TextView" android:gravity="center" android:textColor="#F9A512" android:textStyle="bold" android:textSize="18dp" > </TextView> </LinearLayout>
gridview xml
<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="auto_fit" android:verticalSpacing="10dip" android:horizontalSpacing="10dip" android:stretchMode="columnWidth" android:gravity="center" android:background="#FFFFFF" android:padding="5dip" />
I saw other questions about this same issue, but none of them answered. Any ideas of what's happening?
-
Lucas Jota almost 12 yearsThat worked! Although LogCat keeps displaying those GC_EXTERNAL_ALLOC lines when I first scroll down the grid...
-
user almost 12 years@LucasJota That is the garbage collector, I think it's normal(if it doesn't make the
GridView
laggy). Keep in mind that you're querying for those images and also keeping them in memory(I don't know how many you have). -
Gripsoft almost 12 yearsWhy would you add an extra check, while we we already checked for convertview==null, i would put the last block in else block.
-
osayilgan almost 12 yearsyeah you are right, but it didn't work in the "else statement" for me some how, I'm not sure.
-
ieselisra about 10 yearsWorked perfectly for me with Button + Textview
-
Monzer Yaghi about 9 yearsThank u very much you're a hero
-
Monzer Yaghi over 8 years
-
ArtiomLK over 7 yearsIf you add the
TextView
programmatically. The solution is a little bit different. For example; (Assuming you have a LinearLayout)LinearLayout linearLayout = (LinearLayout)v.findViewById(R.id.NAME_OF_YOUR_LINEARLAYOUT); linearLayout.removeAllViews(); TextView textViewDay = new TextView(mContext); textViewDay.setText("YOURTEXT"); linearLayout.addView(textViewDay);
Therefore,linearLayout.removeAllViews();
would be needed so that you do not end up adding more TextViews on each call togetView(...)
, which is called every time you scroll up or down -
Namrata Bagerwal almost 6 yearsEven though I am doing the same, I don't understand why it's not working. Any help would be appreciated.
-
user almost 6 years@NamrataBagerwal Please post a new question and provide the code you currently use to get help with the problem you have.