アプリを完成させる
次に、ソースを変更していきましょう。[1]~[6]までは前回解説しましたので、[7]から解説することにします。
- [1]プロジェクトの新規作成
- [2]permissionの追加
- [3]レイアウトの変更
- [4]HttpAsyncLoader、ParseJsonクラス、jacksonライブラリの追加
- [5]Instagram API解析クラスの追加
- [6]グリッドビューの表示
- [7]画像表示ライブラリの追加(今回解説)
- [8]画像表示用アダプタークラスの追加(〃)
- [9]グリッドビュー設定、カラム数の動的変更、拡大画像画面の追加(〃)
画像表示ライブラリの追加
画像をダウンロードして表示する処理を、自力でコーディングするのは意外と難しいため、今回は、Picassoという、画像表示ライブラリを利用します。Picassoでは、非同期での画像の読み込み、画像変換、メモリやディスクへのキャッシュといった機能が実装されています。このライブラリを使えば、驚くほどかんたんに、画像を表示することができます。
Picassoのサイトから、jarファイル(執筆時点では、picasso-2.3.2.jar)をダウンロードして、プロジェクトのlibsフォルダにコピーしておきます。
画像表示用アダプタークラスの追加
次に、グリッドビューに表示されるアイテムに、画像をバインドするためのアダプタークラス(GridViewAdapter)を作成しましょう。
前回は、単に文字列を表示するだけでしたので、標準で用意されているArrayAdapterクラスを利用しました。今回は、ArrayAdapterの基本クラスとなっているBaseAdapterを継承して、独自の画像表示用アダプタークラスを作成します。
なお、BaseAdapterを継承する場合は、次のメソッドをオーバーライドする必要があります。
メソッド | 内容 |
---|---|
getCount | ビューに設定するアイテム数 |
getItem | 指定した位置のアイテム内容を返す |
getItemId | 指定した位置のアイテムのIDを返す |
getView | 指定した位置のビューを返す |
public class GridViewAdapter extends BaseAdapter { private List<ImageInfo> urls; // 画像情報のリスト private Context context; public GridViewAdapter(Context context, List<ImageInfo> urls) { this.urls = urls; this.context = context; } @Override public int getCount() { // グリッドビューには、intの最大を設定する(5) return Integer.MAX_VALUE; } @Override public Object getItem(int position) { // サムネイル画像のURLを返す(6) return (urls.size() == 0) ? null : urls.get(position % urls.size()) .getThumbnail(); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { SquaredImageView view = (SquaredImageView)convertView; // ビューの作成が初めてなら(1) if (view == null) { view = new SquaredImageView(context); } // サムネイル画像のURLを取得する(2) String url = (String)getItem(position); // ビューに表示する画像のURLを設定する(3) Picasso.with(this.context).load(url).placeholder(R.drawable.akb_logo) .into(view); return view; } // 標準サイズの画像を設定する(7) public void setStandardImage(int position, ImageView view) { if (0 < urls.size()){ String url = urls.get(position % urls.size()).getStandard(); Picasso.with(this.context).load(url) .placeholder(R.drawable.akb_logo).into(view); } } }
public class SquaredImageView extends ImageView { ~中略~ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // ビューの高さを横幅と同じにする(4) setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); } }
getViewメソッドで、アイテムに表示するビューを設定しています。このメソッドは、グリッドビューの各アイテムが表示される際に、自動的に呼ばれるメソッドです。Picassoライブラリを利用することで、とても短いコードで画像が表示できます。
getViewメソッドの引数のconvertViewには、以前のビューが渡されます。これがnullであれば新規作成する必要があります(1)。画像を表示するURLを取得し(2)、Picassoのメソッドを呼び出します(3)。
Picassoでは、メソッドチェーンが使えて短く記述できます。この部分の構造ですが、最初にPicasso.withメソッドで、デフォルトの設定のPicassoクラスのインスタンスを生成しています。デフォルトの設定は、表のようになっています。
項目 | 設定値 |
---|---|
メモリキャッシュ | 利用可能なメモリの15% |
デスクキャッシュ | 利用可能な容量の2%、ただし最大50MB、最小5MB |
画像を読み込むスレッド数 | 3 |
Picassoクラスのインスタンスの生成後、各メソッドを呼び出します。次の表に示したようなメソッドが用意されています。
メソッド | 概要 |
---|---|
load | 指定したパスやURLから画像を読み込む |
into | 画像を表示するビューを設定する |
placeholder | 最初に表示する画像を設定する |
error | エラー時に表示する画像を設定する |
resize | 画像をリサイズする |
rotate | 画像を回転させる |
なお、SquaredImageViewは、ビューの高さを幅と同じにするビューです。標準のImageViewでは、グリッドビューの高さに応じて、自動的に高さが決められてしまいます。Instagramの画像は正方形なので、それに合うように高さを幅と同じに設定しています(4)。
また、getCountメソッドでは、int型の最大を設定し(5)、getItemメソッドでは、位置を示す引数(0から始まるインデックス)から、実際の画像数で割った余りを求めて(6)、URLを指定しています。
これは何をしているかというと、グリッドビューを下方向にスクロールしていき、最後まで表示した場合に、また先頭から表示するようにするためです。
例えば、画像数が10なら、インデックスが10以上でも、余りは0~9になるので、同じ10枚の画像をくりかえし表示することになります。従って、下方向のスクロールだけで、ずっと全体を表示し続けるようになります。
なおsetStandardImageメソッドは、グリッドビューのアイテムをタップしたときに表示する、拡大画面のビューを設定するためのものです(7)。