2013年9月20日金曜日

GridView(リストの最後まで表示されたら追加する)

前回の「GridViewを使ってみる(SDカードの画像表示) 」で、
SDカードに保存されている画像が大量に有った場合に、
画像が表示がされるまでにだいぶ待たされる事になってしまいます。

そこで、今回はGridViewのデータを動的に追加できる方法を調べてみました!
ついでにGridViewのクリックイベントもつけてあります(ΦωΦ)フフフ…

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview3"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview3.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

■activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">
    <GridView android:id="@+id/gridView1"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:columnWidth="90dp"
     android:numColumns="auto_fit"
     android:verticalSpacing="10dp"
     android:horizontalSpacing="10dp"
     android:stretchMode="columnWidth"
     android:gravity="center"
    />
</LinearLayout>

■MainActivity.java

作成中にはまった点として、スクロールの状態を検知している箇所で、
末尾まで表示したら追加する処理を行う場合に、
今、表示されているデータの末尾の内容が全体の末尾まで読み込まれているか?という判定用に、
GridViewに登録されているデータ数のトータル数を見ているのですが、
そこの値がGridViewの初期化のタイミングでは0が入ってしまっている?っぽくてはまりました。

単純に、現在表示している末尾だけの比較になると、初期化のタイミングでおかしくなってしまうので、
GridViewがスクロールをしている状態の時だけその判定を入れる事で回避してあります。
package com.example.gridview3;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AbsListView.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Toast;

public class MainActivity extends Activity {

 // デフォルトで作成するリストのデータ数
 private static final int LIST_COUNT_MAX = 100;
 // GridViewを追加する際のデータ数
 private static final int LIST_COUNT_ADD_MAX = 40;

 // GirdView
 private GridView mGridView;
 private ArrayList<String> mList;
 private ArrayAdapter<String> mArrayAdapter;

 // スクロール中か
 private static Boolean sScrolling = false;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // データの初期化
  mList = new ArrayList<String>();
  int length = LIST_COUNT_MAX;
  for (int i = 0; i < length; i++) {
   mList.add(String.valueOf(i));
  }

  // アダプターの作成
  mArrayAdapter = new ArrayAdapter<String>(getApplicationContext(),
    android.R.layout.simple_list_item_1, mList);

  // GridViewの取得
  mGridView = (GridView) findViewById(R.id.gridView1);

  // データをGridViewへ設定
  mGridView.setAdapter(mArrayAdapter);

  // スクロールのリスナーを設定
  mGridView.setOnScrollListener(new GridViewOnScrollListener());

  // クリックのリスナーを設定
  mGridView.setOnItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> parent, View v,
     int position, long id) {
    Toast.makeText(getApplicationContext(),
      "onItemClick : " + position, Toast.LENGTH_SHORT).show();
   }
  });

  // 長押しのリスナーを設定
  mGridView.setOnItemLongClickListener(new OnItemLongClickListener() {

   @Override
   public boolean onItemLongClick(AdapterView<?> parent, View v,
     int position, long id) {
    Toast.makeText(getApplicationContext(),
      "onItemLongClick : " + position, Toast.LENGTH_SHORT)
      .show();
    // 長押しのイベント発生後にクリックイベントを発生させない為にfalseで返す
    return false;
   }

  });

 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 /*
  * スクローラーの状態検知
  */
 public class GridViewOnScrollListener implements OnScrollListener {

  /*
   * ステータスが変わった時
   * 
   * @see
   * android.widget.AbsListView.OnScrollListener#onScrollStateChanged(
   * android.widget.AbsListView, int)
   */
  @Override
  public void onScrollStateChanged(AbsListView paramAbsListView,
    int scrollState) {
   switch (scrollState) {

   // スクロール停止
   case OnScrollListener.SCROLL_STATE_IDLE:

    // decode処理をqueueに登録して開始する記述
    sScrolling = false;

    // アダプターにデータ変更の通知
    mArrayAdapter.notifyDataSetChanged();
    // GridViewの再描画
    mGridView.invalidateViews();

    break;

   // スクロール
   case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
    // decodeのqueueをキャンセルする処理を記述
    sScrolling = true;
    break;

   // フリック
   case OnScrollListener.SCROLL_STATE_FLING:
    // decodeのqueueをキャンセルする処理を記述
    sScrolling = true;
    break;

   default:
    break;
   }
  }

  /*
   * スクロール中
   * 
   * @see
   * android.widget.AbsListView.OnScrollListener#onScroll(android.widget
   * .AbsListView, int, int, int)
   */
  @Override
  public void onScroll(AbsListView view, int firstVisibleItem,
    int visibleItemCount, int totalItemCount) {

   // 現在表示されているリストの末尾番号
   int displayCount = firstVisibleItem + visibleItemCount;

   /*
    * 
    * 初期でdisplayCountに数値が入ってるのに、totalItemCountが0の場合があるためスクロール中のみ判定するようにする
    * 。
    */
   if (displayCount < totalItemCount || !sScrolling) {
    return;
   }

   // リストの最大値を取得する
   int start = mList.size();
   // リストの最大値+追加する数
   int length = start + LIST_COUNT_ADD_MAX;

   // リストにデータ追加
   for (int i = start; i < length; i++) {
    mList.add(String.valueOf(i));
   }

   // アダプターにリストデータ変更の通知
   mArrayAdapter.notifyDataSetChanged();

   // GridViewの再描画
   mGridView.invalidateViews();

  }

 }

}
実行結果は次のようになります。

以上です(`・ω・´)ゞビシッ!!

参考URL

0 件のコメント:

コメントを投稿