Upgrade to Pro — share decks privately, control downloads, hide ads and more …

やさしい画像ギャラリー改善tips

 やさしい画像ギャラリー改善tips

Yuichi Maekawa

April 20, 2017
Tweet

More Decks by Yuichi Maekawa

Other Decks in Programming

Transcript

  1. やさしい
    画像ギャラリー改善tips
    @kaelaela

    View Slide

  2.    まえかわ ゆういち(kaelaela)
    ● Github: kaelaela
    ● Twitter: kaelaela31
    ● 755というSNSを作っています

    View Slide

  3. 注意
    画像ギャラリー ≠ 画像一覧
    画像ギャラリーとは端末内の画像を選択する画面のこと

    View Slide

  4. 対象としている人
    ● 画像ギャラリーよくしたかったんだよね
    ● いろいろ調べたけど諦めた
    ● スケジュール的に泣く泣くある程度のものにしてた

    View Slide

  5. 対象じゃない人
    ● 画像ギャラリー作成は一通り悩んだ
    ● うちには画像ギャラリーが必要ない

    View Slide

  6. 話さないこと
    ● Intentの概念、使い方など
    ● ContentResolverの説明など
    ● 画像キャッシュに関すること
    ● APIからリストを取得し表示すること

    View Slide

  7. ゴール
    「簡単そうだな」
    「画像選択画面のパフォーマンスを改善しました」リリース

    View Slide

  8. 画像ギャラリー苦しみあるある
    ● スクロールするとカクつく
    ● ローディングが終わらない or 何度も呼び出される
    ● キャッシュが効くまでは遅い
    ● Android標準のギャラリーが開く
    (Storage Access Framework)

    View Slide

  9. Storage Access Framework
    ● MIME typeで指定できるが、関係のないフォルダの参照などもある
    ● デザインの変更ができない
    ● 公式ドキュメント
    https://developer.android.com/guide/topics/providers/document-provider.html
    //Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKA
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*"); //画像のみの場合
    startActivityForResult(intent, YOUR_REQUEST_CODE);

    View Slide

  10. Storage Access Framework
    ● MIME typeで指定できるが、関係のないフォルダの参照などもある
    ● デザインの変更ができない
    ● 公式ドキュメント
    https://developer.android.com/guide/topics/providers/document-provider.html
    //Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKA
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*"); //画像のみの場合
    startActivityForResult(intent, YOUR_REQUEST_CODE);
    デザイナーが
    許してくれない

    View Slide

  11. こんな画像ギャラリーにしたい
    ● 読み込みとスクロールが早い
    ● デザインが自由にできる
    ● 自分たちのアプリで必要な機能に絞る

    View Slide

  12. 改善のポイント3つ
    ● 画像管理方法を理解する
    ● 適切なサイズの画像を使う
    ● 使い方に合わせて表示する

    View Slide

  13. ポイント1: 画像の管理方法を理解する
    ● 保存されている画像について
    ● MediaStoreのイメージ図
    ● 画像へのアクセス方法

    View Slide

  14. 保存されている画像について
    形式: 基本は撮影したjpgやダウンロードしたpng
    MediaStore:端末内データのメタ情報を提供している
    Audio, Files, Images, Video, MediaColumns
    https://developer.android.com/reference/android/provider/MediaStore.html#

    View Slide

  15. MediaStoreのイメージ図
    Files
    - FileColumns
    - MEDIA_TYPE
    - MIME_TYPE
    - TITLE
    ...
    その他、有象無象
    Audio
    - Media
    - Alubms
    - Artists
    ...
    Images
    - Media
    - Thumbnails
    - ImageColumns
    Video
    - Media(本体)
    - Thumbnails
    - VideoColumns

    View Slide

  16. 画像を取得
    Files
    - FileColumns
    - MEDIA_TYPE
    - MIME_TYPE
    - TITLE
    ...
    その他、有象無象
    Audio
    - Media
    - Alubms
    - Artists
    ...
    Images
    - Media
    - Thumbnails
    - ImageColumns
    Video
    - Media(本体)
    - Thumbnails
    - VideoColumns
    ここから取得
    MediaStore.Images.Media

    View Slide

  17. 画像と動画を取得
    Files
    - FileColumns
    - MEDIA_TYPE
    - MIME_TYPE
    - TITLE
    ...
    その他、有象無象
    Audio
    - Media
    - Alubms
    - Artists
    ...
    Images
    - Media
    - Thumbnails
    - ImageColumns
    Video
    - Media(本体)
    - Thumbnails
    - VideoColumns
    ここから取得
    =MediaStore.Filesで
    MEDIA_TYPE_IMAGE,MEDIA_TYPE_VIDEOを指定

    View Slide

  18. 画像へのアクセスの方法
    ContentResolverでアクセス
    https://developer.android.com/reference/android/content/ContentResolver.html
    Cursorで取得
    SQLでいう「CURRENT OFカーソル名」のカーソル

    View Slide

  19. 画像へのアクセスの方法
    ContentResolver r = context.getContentResolver();
    Cursor c = r.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null, null, null, null);
    if (c != null) {
    c.moveToFirst();
    while (!c.isAfterLast()) {
    String data = c.getString(c.getColumnIndex(MediaStore.Images.Thumbnails.DATA));
    String imageId = c.getString(c.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID));
    thumbnailPaths.add(data);
    thumbnailIds.add(imageId);
    c.moveToNext();
    }
    c.close();
    }

    View Slide

  20. 画像へのアクセスの方法
    ContentResolver r = context.getContentResolver();
    Cursor c = r.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null, null, null, null);
    if (c != null) {
    c.moveToFirst();
    while (!c.isAfterLast()) {
    String data = c.getString(c.getColumnIndex(MediaStore.Images.Thumbnails.DATA));
    String imageId = c.getString(c.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID));
    thumbnailPaths.add(data);
    thumbnailIds.add(imageId);
    c.moveToNext();
    }
    c.close();
    }

    View Slide

  21. ポイント2: 適切なサイズを使う
    たいていの記事では
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    を使っているので、もとのサイズのイメージを読み込んでいる
    MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI
    を使いましょう
    Thumbnailのサイズ
    ● MINI_KIND: 512 x 384
    ● MICRO_KIND: 96 x 96

    View Slide

  22. MediaStoreのイメージ図
    Files
    - FileColumns
    - MEDIA_TYPE
    - MIME_TYPE
    - TITLE
    ...
    その他、有象無象
    Audio
    - Media
    - Alubms
    - Artists
    ...
    Images
    - Media
    - Thumbnails
    - ImageColumns
    Video
    - Media(本体)
    - Thumbnails
    - VideoColumns

    View Slide

  23. 注意
    ● Thumbnailは回転情報がなく、横向きで表示されるものもある
    「 CursorJoinerを使ってMediaStore.Images.Thumbnailsに回転情報を追加する」
    tomoima525さん
    http://qiita.com/tomoima525/items/762a55a86b3decf05d55
    ● Thumbnailをそのまま使用しないように気をつける
    MediaStore.Images.Thumbnails.IMAGE_IDとMediaStore.Images.Media._IDが等しいことを利用

    View Slide

  24. MediaStoreのイメージ図
    Files
    - FileColumns
    - MEDIA_TYPE
    - MIME_TYPE
    - TITLE
    ...
    その他、有象無象
    Audio
    - Media
    - Alubms
    - Artists
    ...
    Images
    - Media
    - _ID
    - Thumbnails
    - IMAGE_ID
    - ImageColumns
    Video
    - Media(本体)
    - Thumbnails
    - VideoColumns
    等しい

    View Slide

  25. ポイント3: 使い方に合わせて表示する
    ● メッセージやSNSなど: 今撮ったsnowの写真がほしい
    → 撮影した写真が上に来るように
    → 選択したらすぐに送信できるように
    ● 画像加工など: プレビューしてから選ぶかもしれない
    → 拡大縮小できるプレビューを挟む
    → サムネイルじゃだめ(えっ

    View Slide

  26. サンプルつくりました
    ● 普通の3カラムサンプル
    ● Facebook Messengerサンプル
    ● InstagramのDMサンプル
    https://github.com/kaelaela/AndroidImageGallerySample
    ※API level 16以上

    View Slide

  27. ありがとうございました!

    View Slide