閉じる

photoviewersampleを 2.xで動かしてみる

ViewPagerで画像の表示をし、ピンチイン/アウトで拡大縮小、ドラッグでスクロール、フリップでページ変更というのを自分で実装してみたけど、「この UI自体はフォトビュワー系のアプリではよく見るけど、みんなシコシコとコード書いているのか?もっと楽な方法があるのでは?」と SDKを漁っていたら、PhotoViewPagerなんてのが目に付いた。*1
ソレを使うサンプルも存在する。*2
中を見てみると ActionBarとか Fragmentとか使っているので 3.xから存在するのかな?
で、今は SupportLibraryを使えば 2.xでもそれらは使えるので動かしてみた。*3

SDKマネージャから落とせるソースに含まれるのは本当にソースコードだけなので AOSPのツリーからリソースを含めて落としてくる。*4

asahina@lachesis:~$ mkdir ex
asahina@lachesis:~$ cd ex
asahina@lachesis:~/ex$ git clone https://android.googlesource.com/platform/frameworks/ex/
Cloning into 'ex'...
remote: Counting objects: 75, done
remote: Finding sources: 100% (75/75)
remote: Total 9040 (delta 3826), reused 9040 (delta 3826)
Receiving objects: 100% (9040/9040), 4.60 MiB | 3.81 MiB/s, done.
Resolving deltas: 100% (3826/3826), done.
Checking connectivity... done
asahina@lachesis:~/ex$ cd ex/
asahina@lachesis:~/ex/ex$ git checkout android-4.2.2_r1.2
Note: checking out 'android-4.2.2_r1.2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

HEAD is now at a918fec... Merge "Eliminate jank when the user deletes a character thereby removing all contact results in the popup." into jb-mr1.1-dev
asahina@lachesis:~/ex/ex$ ls
CleanSpec.mk carousel/ chips/ common/ photoviewer/ variablespeed/ widget/
asahina@lachesis:~/ex/ex$ ls photoviewer/
Android.mk AndroidManifest.xml res/ sample/ src/

基本的には Fragmentや Loader系を SupportLibraryの物に差し替え、ActionBar系を android.support.v7.app.ActionBarを参照して書き換え、3.x以降でしか使えないメソッドやアトリビュート*5 を使わないようにしただけ。

プロジェクトの準備

  • eclipseから android-support-v7-appcompat,photoviewer,photoviewer/sampleをインポート
  • photoviewerをライブラリに設定
  • photoviewerのライブラリとして android-support-v7-appcompatを設定
  • photoviewer/sampleのライブラリとして photoviewerを設定

importをひたすら書き換え

  • android.app.Fragmentを android.support.v4.app.Fragment
  • android.app.FragmentManagerを android.support.v4.app.FragmentManager
  • android.app.FragmentTransactionを android.support.v4.app.FragmentTransaction
  • android.app.LoaderManagerを android.support.v4.app.LoaderManager
  • android.app.LoaderManager.LoaderCallbacksを android.support.v4.app.LoaderManager.LoaderCallbacks
  • android.app.ActionBar.OnMenuVisibilityListenerを android.support.v7.app.ActionBar.OnMenuVisibilityListener
  • android.app.ActionBarを android.support.v7.app.ActionBar
  • android.content.Loaderを android.support.v4.content.Loader
  • android.content.AsyncTaskLoaderを android.support.v4.content.AsyncTaskLoader
  • android.content.CursorLoaderを android.support.v4.content.CursorLoader
  • android.util.LruCacheを android.support.v4.util.LruCache

Activityを書き換え

  • android.app.Activityを android.support.v7.app.ActionBarActivity

メソッド呼び出しを書き換え

  • getActionBar()を getSupportActionBar()
  • getFragmentManager()を getSupportFragmentManager()
  • ViewPager.setSystemUiVisibilityは削除

リソースを書き換え

  • photo_fragment_view.xmlの「android:background=”?android:attr/selectableItemBackground”」を削除
  • styleの PhotoViewThemeは android:windowNoTitleに falseを設定しているけど、trueに変更。
    ただし、trueにすると API11以降(?)の環境では落ちるので values-v11/を作って変更前を振り分けてあげる。
  • styleの PhotoViewThemeの親を「android:Theme.Holo」から「Theme.AppCompat」へ変更。

AndroidManifest.xmlを書き換え

  • android:theme=”@style/AppTheme”を android:theme=”@style/Theme.AppCompat”に
  • android:minSdkVersionは 7に設定

動きを見る分にはこれだけで十分動作した。*6
動きを見ればわかるけど、PhotoViewPagerというのは標準アプリの「ギャラリー」の実装の一部だと思われる。
PhotoViewPager自体の機能も期待通りで、これを手直しした上で自作した部分を置き換えることに。
ちなみにコードを読んでみると、うんざりするぐらい泥臭いコードが並んでいた。

2013/09/07追記

一度フルスクリーン表示にした後、フルスクリーン表示を解除すると一定時間後にフルスクリーン表示になるけど、フルスクリーンになったというフラグが立たないので動作がおかしくなるのはバグかな。
とりあえず一定時間後にフルスクリーンにする指定を殺して回避。
4.2.2_r1.2のタグより後ろは photoviewer/の下に .gitignoreしかなくて更新内容が不明なんよね。

で、探し歩いていたら、独立したツリーとして発見。</platform/frameworks/opt/photoviewer/

サンプルをビルドしてみると、件のバグっぽい動作も修正されている。

基本的には上述の変更方針でいけるけど、4.3ベースのバージョンでは Fragmentが既に SupportLibraryの物を使っているので変更は ActionBar周りだけになり、修正量はかなり少ない。

ただし、4.2ベース(android-4.2.2_r1.2)から 4.3ベース(android-4.3_r2.2)への変更がそれなりに入っているので 4.2ベースからの派生コードを 4.3ベースからの派生コードにするのは派生の仕方によっては多少時間がかかるかもしれず。

2013/11/08追記

4.4ベース(android-4.4_r1)のコードを眺めてみたけど、かなりの変更が入っているね。

ただ、ActionBar周りが AppCompatを使った実装とネイティブのを使った実装の両方入っているので単純にビューワとして使うだけならすごく簡単。

AndroidManifest.xml,src/,res/をコピーし、AppCompatを使うなら appcompat/以下、ネイティブなら activity/以下の src/,res/を上書き。*7

eclipseからインポートしライブラリとして設定。

自分のアプリは sample/を参考に ContentProviderを定義して PhotoViewActivityを呼び出すだけ。


*1 普通のサンプルではなく、ソースに含まれる sources/android-17/com/android/ex/photo/PhotoViewPager.java

*2 sources/android-17/com/example/photoviewersample/

*3 拙作アプリ群は既に 2.2以下を切り捨てているので実質的に 2.3でという事になる。

*4 バージョンに深い意味はない。

*5 今回の移植に関しては見栄え系の物だけだった

*6 実際には 2.xxと 3.xx挙動の違いから Bitmapの recycle周りだけでも手を加える必要がある思う。

*7 テーマと PhotoViewActivityの実装を分けているだけ。

コメントを残す

メールアドレスが公開されることはありません。必須項目には印がついています *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)