ListViewにサムネイルを表示する

前回記事ではCursorAdapterの拡張を行ってMyCursorAdapterクラスを作ったが、今回はそれをベースに少し改造を行って写真サムネイルのListView表示を目標にする。

スポンサーリンク

ListViewレイアウトの準備

今回はサムネイル表示を行うためにImageViewを使う。前回記事でDBのレコードIDを表示していた左端を96×96ピクセルのImageViewに変更し、ImageViewより右側は高さを同じにしての残りの幅を写真URI表示用のTextViewとした。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/thumbnail"
        android:layout_width="96dp"
        android:layout_height="96dp"
        android:padding="3dp" />

    <TextView
        android:id="@+id/uri"
        android:layout_width="match_parent"
        android:layout_height="96dp"
        android:padding="3dp" />
</LinearLayout>

CursorAdapter拡張クラスの変更

CursorAdapter拡張クラスであるMyCursorAdapterを変更する。といっても、ほぼ前回記事と同じ。

package com.example.photologger;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.Thumbnails;
import android.support.v4.os.CancellationSignal;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class MyCursorAdapter extends CursorAdapter {
    private LayoutInflater mCursorInflater;
    private ContentResolver mContentResolver;

    public MyCursorAdapter(Context context, Cursor c, int flags)
    {
        super(context, c, flags);
        mCursorInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContentResolver = context.getContentResolver();
    }
    static class ViewHolder {
        ImageView tn_img;;
        TextView uri_text;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
        View view = mCursorInflater.inflate(R.layout.list_item, null);

        ViewHolder holder = new ViewHolder();
        holder.tn_img = (ImageView) view.findViewById(R.id.thumbnail);
        holder.uri_text = (TextView) view.findViewById(R.id.uri);

        view.setTag(holder);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ViewHolder holder = (ViewHolder) view.getTag();

        //        int id = cursor.getInt(0);
        String photoUri = cursor.getString(1);

        long tnid = Long.parseLong(photoUri.substring(photoUri.lastIndexOf("/") + 1));
        Bitmap img = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver, tnid, MediaStore.Images.Thumbnails.MICRO_KIND,null);
        holder.tn_img.setImageBitmap(img);
        holder.uri_text.setText(photoUri);
    }
}

変更箇所を詳しく見ると、まずViewHolderがImageView導入によって変わっている。

    static class ViewHolder {
        ImageView tn_img;;
        TextView uri_text;
    }

newViewメソッドは上記ViewHolderの型が変わったことによる小変更のみ。そして、一番の変更点はbindViewメソッドでImageViewにサムネイルの画像を渡している下記のコード。

        long tnid = Long.parseLong(photoUri.substring(photoUri.lastIndexOf("/") + 1));
        Bitmap img = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver, tnid, MediaStore.Images.Thumbnails.MICRO_KIND,null);
        holder.tn_img.setImageBitmap(img);

サムネイルを取得するメソッドを利用して簡単に実現出来た。但し、今回使ったMediaStore.Images.Thumbnails#getThumbnailメソッドはAndroid SDK本家サイトによると、クラス自体が非推奨になってしまったらしい。
代替として ContentResolver#loadThumbnailがオススメされており、こっちの方がURI指定で直接サムネイルを取ってこれるので便利そうだが、API Level29以降でないと使えないと。デバッグに使っている古いスマホがAPI Level28じゃないと駄目なので、今回はやむを得ず上記のコードとした。

実行結果

まず、縦位置でのスクショ。(家の中の色んなものが写り込んでもアレなので、デバッグ中の無意味なPC画面です(笑)

そして、横位置でのスクショ。

サムネイルのサイズ以外はレイアウトの指定に絶対値を使っていないので、画面回転をしても特に問題無く動作する。

コメント