GridViewを使用して、ユーザーが選択できる一連のカテゴリを表示しています。グリッドの各アイテムは、サーバーから取得されたImageViewとTextViewで構成されています。アイテムに触れると、別のアクティビティが開始されます。
画面をスクロールしたときにいくつかのイテンが繰り返されていることに気付くまで、すべてが順調に進んでいると思いました。グリッドを下にスクロールしてから戻ると、位置が変わり、複製されます。しかし、めちゃくちゃなitensに触れても、正しい値が次のアクティビティに送信されます。
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
スクロールするたびに、itensが再描画されるように見えます...
更新:GridViewを初めて下にスクロールしたときにのみ再描画されます。この後、繰り返されるものを含むすべてのイテンは、その場所に留まります。
私の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クラス
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"
/>
この同じ問題について他の質問を見ましたが、どれも答えませんでした。何が起こっているのかについてのアイデアはありますか?
GridView
メソッドでは、getView
の場合にのみ、ImageView
のドローアブルを設定するため、convertView
を下にスクロールすると同じアイテムが表示されるのが普通です。はnull
です(たとえば、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;
}
position
パラメータを使用してデータを取得するため、要素をクリックすると正しいアイテムが表示されます。
これらは、ボタン+テキストビューを備えたGridViewのコードです。
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;
}
ここを変更して、もう一度試してください。
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;
}
送信して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");
}
});
ViewHolder
静的クラスを使用すると、繰り返し項目が修正されました。
また、layout_width
とlayout_height
をfill_parent
に変更しても効果はありませんでした。
このチュートリアルを実行しました http://Android-vogue.blogspot.com/2011/06/custom-gridview-in-Android-with.html