事前に定義された数のアイテムに制限されたグリッドビューを含む複数のページを持つビューページャーがあります。
グリッドビューはカスタム アダプターを使用します。このアダプターは、ページごとに json リストから事前定義された数のアイテムを表示し、各ページはアイテムに関して最後のページが残った場所から続きます。
私が抱えている問題は、アイテムをクリックしてから戻ってリストにアクセスすると、別のアイテムをクリックすると無効なインデックスエラーが返されることです。
以下の私の完全なコード:
package com.guessthegame;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.viewpagerindicator.LinePageIndicator;
import android.os.Bundle;
import android.os.Parcelable;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.app.NavUtils;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
public class GamesList extends Activity {
static String file, name, desc, img = "";
GameListAdaptor adaptor;
GridView listViewGames;
static TextView Tname;
static TextView Tdesc;
static TextView Tcount;
ViewPager myPager;
int perPage = 12;
int gamesCnt = 0;
int pagesNo = 1;
int currentPage = 0;
private class MyPagerAdapter extends PagerAdapter {
public int getCount() {
pagesNo = (int) Math.ceil(((float) gamesCnt / (float) perPage));
return (pagesNo > 1 ? pagesNo : 1 );
}
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(getBaseContext().LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.activity_games_list, null);
((ViewPager) collection).addView(view, 0);
adaptor = new GameListAdaptor(getBaseContext(),R.layout.game, loadGames(position+1));
listViewGames = (GridView) view.findViewById(R.id.games);
listViewGames.setClickable(true);
listViewGames.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
// if(position <= loadGames(position+1).size()) {
Games games = adaptor.getItem(position);
Intent intent = new Intent(GamesList.this, Game.class);
intent.putExtra("FILE", file);
intent.putExtra("IMG", games.img);
intent.putExtra("HINT", games.hint);
intent.putExtra("SOUND", games.sound);
intent.putExtra("ANSWER", games.answer);
intent.putExtra("CLOSE", games.close);
startActivity(intent);
// }
}
});
listViewGames.setAdapter(adaptor);
adaptor.setNotifyOnChange(true);
return view;
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
@Override
public Parcelable saveState() {
return null;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_games_page);
// Show the Up button in the action bar.
//getActionBar().setDisplayHomeAsUpEnabled(true);
Bundle extras = getIntent().getExtras();
if(extras != null) {
file = extras.getString("FILE");
name = extras.getString("NAME");
desc = extras.getString("DESC");
img = extras.getString("IMG");
}
if(file != "") {
gamesCnt = MainActivity.prefs.getInt(file+"_cnt", 0);
MyPagerAdapter adapterP = new MyPagerAdapter();
myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
myPager.setAdapter(adapterP);
//myPager.setCurrentItem(0);
//Bind the title indicator to the adapter
LinePageIndicator titleIndicator = (LinePageIndicator)findViewById(R.id.indicator);
titleIndicator.setViewPager(myPager);
//new LoadJsonTask().execute();
}
}
@Override
public void onResume() {
// After a pause OR at startup
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.activity_games_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private ArrayList<Games> loadGames(int position) {
ArrayList<Games> games = new ArrayList<Games>();
String jsonString = null;
InputStream in;
try {
in = this.getAssets().open(file);
int size = in.available();
byte[] buffer = new byte[size];
in.read(buffer);
in.close();
jsonString = new String(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
JSONObject jsonObj = new JSONObject(jsonString);
JSONArray gamesArr = jsonObj.getJSONArray("games");
int gamesCnt = gamesArr.length();
int startNo = (position == 1 ? 0 : (position-1) * perPage + 1);
int endNo = ((startNo+perPage) > gamesCnt ? gamesCnt : (startNo+perPage));
Log.i("info",position + " - " + startNo + " <= " + endNo + " | " + gamesArr.length());
for(int currentNo = startNo; currentNo < endNo; currentNo++) {
JSONObject j = gamesArr.getJSONObject(currentNo);
Games game= new Games();
game.img = (j.getString("img") != "" ? j.getString("img") : "" );
game.hint = (j.getString("hint") != "" ? j.getString("hint") : "" );
game.sound = (j.getString("sound") != "" ? j.getString("sound") : "" );
game.answer = (j.getString("answer") != "" ? j.getString("answer") : "" );
game.close = (j.getString("close") != "" ? j.getString("close") : "" );
games.add(game);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return games;
}
}
ログキャット:
03-19 17:51:31.838: E/AndroidRuntime(14573): FATAL EXCEPTION: main
03-19 17:51:31.838: E/AndroidRuntime(14573): java.lang.IndexOutOfBoundsException: Invalid index 9, size is 0
03-19 17:51:31.838: E/AndroidRuntime(14573): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
03-19 17:51:31.838: E/AndroidRuntime(14573): at java.util.ArrayList.get(ArrayList.java:304)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.widget.ArrayAdapter.getItem(ArrayAdapter.java:337)
03-19 17:51:31.838: E/AndroidRuntime(14573): at com.guessthegame.GamesList$MyPagerAdapter$1.onItemClick(GamesList.java:71)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.widget.AdapterView.performItemClick(AdapterView.java:298)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.widget.AbsListView$1.run(AbsListView.java:3423)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.os.Handler.handleCallback(Handler.java:725)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.os.Handler.dispatchMessage(Handler.java:92)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.os.Looper.loop(Looper.java:137)
03-19 17:51:31.838: E/AndroidRuntime(14573): at android.app.ActivityThread.main(ActivityThread.java:5041)
03-19 17:51:31.838: E/AndroidRuntime(14573): at java.lang.reflect.Method.invokeNative(Native Method)
03-19 17:51:31.838: E/AndroidRuntime(14573): at java.lang.reflect.Method.invoke(Method.java:511)
03-19 17:51:31.838: E/AndroidRuntime(14573): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-19 17:51:31.838: E/AndroidRuntime(14573): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-19 17:51:31.838: E/AndroidRuntime(14573): at dalvik.system.NativeStart.main(Native Method)
各ページにグリッドビューを追加し、onclickリスナーがどのビューから位置を取得するかを知らないためだと思います。どうすればこれを回避できますか?