Android 屏幕滚动时,GridView 中的项目会重复

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11245620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:30:32  来源:igfitidea点击:

Items inside GridView getting repeated when screen scrolls

androidandroid-layoutgridviewdrawable

提问by Lucas Jota

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.

我正在使用 GridView 来显示一组用户可以选择的类别。网格的每一项都由一个 ImageView 和一个 TextView 组成,两者都从服务器检索。当一个项目被触摸时,另一个活动开始。

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:

查看 LogCat,任何对服务器的重复请求都会发生。事实上,我在滚动时得到了这个:

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.

更新:它只在我第一次向下滚动 GridView 时重绘 itens。在此之后,所有 itens,包括重复的 itens,都会保持原位。

My java class:

我的java类:

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

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

<?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?

我看到了关于同一问题的其他问题,但没有人回答。对正在发生的事情有什么想法吗?

回答by Luksprog

It's normal that you see the same items as you scroll down the GridViewbecause in the getViewmethod you set the drawables for the ImageViewonly when the convertViewis null(for example for the first elements that are seen when the GridViewappear on the screen). If the convertViewis 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 getViewmethod like this:

这是正常的,你看到相同的项目,你向下滚动GridView,因为在getView方法设置为可绘制的ImageView,只有当convertViewnull(例如,用于当所看到的第一个元素GridView出现在屏幕上)。如果convertView不是null,则意味着您有一个回收的行视图,您没有设置正确的图像,您将保留之前在此回收视图上设置的图像。尝试getView像这样修改方法:

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 positionparameter to retrieve the data.

单击一个元素会显示正确的项目,因为您使用position参数来检索数据。

回答by ieselisra

These is my code for GirdView with Button + Textview

这些是我的带有 Button + Textview 的 GirdView 代码

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;
    }

回答by Krste Moskov

Send and gridview or listview and In constructor implement this method implement onscroll listener

Send 和 gridview 或 listview 并在构造函数中实现此方法实现 onscroll 侦听器

    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");
        }
    });

回答by Nikolay Podolnyy

Using ViewHolderstatic class fixed repeating items for me.

ViewHolder为我使用静态类固定重复项。

Also changing layout_widthand layout_heightto fill_parentdidn't help.

也在改变layout_widthlayout_heightfill_parent没有帮助。

I went through this tutorial http://android-vogue.blogspot.com/2011/06/custom-gridview-in-android-with.html

我浏览了本教程 http://android-vogue.blogspot.com/2011/06/custom-gridview-in-android-with.html

回答by osayilgan

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;
}