Reputation: 1873
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?
Upvotes: 20
Views: 22806
Reputation: 1091
Using ViewHolder
static class fixed repeating items for me.
Also changing layout_width
and layout_height
to fill_parent
didn't help.
I went through this tutorial http://android-vogue.blogspot.com/2011/06/custom-gridview-in-android-with.html
Upvotes: 0
Reputation: 157
Send and gridview or listview and In constructor implement this method implement onscroll listener
this.mGridView = mGridView;
this.mGridView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
Log.v("onScrollStateChanged", "onScrollStateChanged");
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
isScrollStop = true;
notifyDataSetChanged();
} else {
isScrollStop = false;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
Log.v("onScroll", "onScroll");
}
});
Upvotes: 0
Reputation: 384
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;
}
Upvotes: 2
Reputation: 5893
Change here and try it again,
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]);
} else {
v = (View) convertView;
}
if(view!=null)
{
ImageView image = (ImageView)v.findViewById(R.id.grid_item_image);
image.setImageDrawable(mThumbIds[position]);
notifyDataSetChanged(); //Calling this helped to solve the problem.
}
return v;
}
Upvotes: 0
Reputation: 87064
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.
Upvotes: 84