web-dev-qa-db-ja.com

UIScrollView画像/写真ビューアー、ページングを有効にしてズーム

OK、私はこの問題のためにインターネット上で公式の場所を作る時だと思います:ページングとズームでUIScrollViewフォトビューアーを作る方法。仲間のUIScrollViewハッカーを歓迎します。

ページングを有効にしたUIScrollViewがあり、組み込みの写真アプリのようにUIImageViewsを表示しています。 (この音はまだおなじみですか?)

Githubで次のプロジェクトを見つけました。

https://github.com/andreyvit/ScrollingMadness/wiki

これは、ページングが有効なときにスクロールビューでズームを実装する方法を示しています。他の誰かがこれを試してみると、実際にはUIScrollViewサブクラスを削除し、ネイティブクラスを使用する必要があります。そうしないと機能しません。スクロールビューがタッチイベントをインターセプトする方法に関連する3.0 SDKの変更が原因だと思います。

そのため、ズームを開始するときに他のすべてのビューを削除し、scrollviewで現在のビューを(0、0)に移動し、contentsizeなどを更新します。 1.0fに戻ると、他のビューが追加され、すべてが順番に戻ります。

とにかく、そのプロジェクトはシミュレーターで完全に動作しますが、デバイス上では、サイズ変更するビューの不快な動きがあります。これは、contentsize/offsetなど。サイズ変更中のビューの場合。このビューを移動する必要があります。そうしないと、他のビューによって残された空白を左にパンできます。

.0 SDKリリースノート の「既知の問題」に興味深いメモを見つけました。

UIScrollView:ズーム後、コンテンツのインセットは無視され、コンテンツは間違った位置に残ります。

この種の音は、ここで何が起こっているかのように聞こえます。ズームイン後、オフセットなどを変更したため、ビューは画面外に移動します。

私はすでにこれに何時間も費やしており、これがうまくいかないという悲しい認識にゆっくりと近づいています。

Three20の写真ビューアーは問題外です。重量が重すぎ、不要なUIやその他の動作が多すぎます。

内蔵の写真アプリはいくつかの魔法を行うようです。画像を拡大して遠端にパンすると、現在の写真はその隣の写真とは独立して移動しますが、これは標準のUIScrollViewで試したときに得られるものではありません。

UIScrollViewのネストについての議論を見てきましたが、実際にそこに行きたくありません。

誰もがこれを標準のUIScrollViewで管理していますか(また、2.2および3.0 SDKで動作します)?私は自分のズーム+バウンス+パン+ページングコードを好みません。

55
Mike Weller

[〜#〜] update [〜#〜]

以下のニュースのため、以前の回答を削除しました...

聞いたことがない人のためのビッグニュース。 Appleはiphone開発者プログラムのすべてのメンバーに2010 WWDCセッションビデオをリリースしました。議論されているトピックの1つは、写真アプリの作成方法です!!!すべてのコードを無料で利用できるようにしました。

プライベートAPIも使用しません。サンプルコードのダウンロードへのリンクを次に示します。アクセスするには、おそらくログインする必要があります。

これをチェック

そして、ここにiTunes WWDCページへのリンクがあります:

これをチェック

43
Jonah

MWPhotoBrowser と呼ばれるシンプルで使いやすい写真ブラウザを作成しました。必要なのは写真ビューアーだけだったので、Three20は重すぎて肥大化していたので、作成することにしました。

MWPhotoBrowserは、UIImageオブジェクト、またはファイル、Webイメージ、またはライブラリアセットへのURLを提供することにより、1つ以上のイメージを表示できます。写真ブラウザは、Webからの写真のダウンロードとキャッシュをシームレスに処理します。写真はズームおよびパンでき、オプションの(カスタマイズ可能な)キャプションを表示できます。ブラウザを使用して、ユーザーがグリッドビューまたはメインイメージビューを使用して1つ以上の写真を選択できるようにすることもできます。

MWPhotoBrowser Screenshots

32

UIScrollViewをネストすることの議論を見たことがあると言いますが、そこに行きたくありません-しかし、それは行く方法です!簡単かつうまく機能します。

基本的には、AppleはPhotoScrollerの例(およびJonahの回答でリンクされた2010 WWDCトーク)で行います。これらの例でのみ、複雑なタイリングやその他のメモリ管理を追加しました。 。タイリングなどを必要とせず、これらの例を繰り返して、それに関連するビットを削除しようとしない場合、UIScrollViewsをネストする基本的な原則は実際には非常に簡単です。

  • 外側のUIScrollViewを作成し、pagingEnabled = trueに設定します。メインビューに追加し、その幅と高さをメインビューの幅と高さに設定します。

  • 必要な数の内部UIScrollViewを作成します。メインビューの幅と高さに幅と高さを設定します。それらを外側のUIScrollViewにサブビューとして追加します。それぞれを左から右に並べて追加します。

  • 外側のUIScrollViewのコンテンツサイズを、内側のすべてのUIScrollViewsの幅の合計([メインビューの幅] * [画像の数]と等しい)に設定します。

  • 画像のUIImageViewsを内側のUIScrollViewsに追加し、1つのUIImageViewを各内側のUIScrollViewに追加します。各UIScrollViewのコンテンツサイズを各UIImageViewのサイズに設定します。

  • 各内部UIScrollViewの最小および最大ズームスケールを設定し、各内部UIScrollViewのデリゲートをView Controllerに設定します。デリゲートのviewForZoomingInScrollViewで、渡されたUIScrollViewの適切なUIImageViewを返します。 (これを行うには、各UIImageViewをNSArrayに保持し、対応するUIScrollViewのタグプロパティを適切なUIImageViewのインデックスに設定します。その後、viewForZoomingInScrollViewに渡されるUIScrollViewのタグを読み取り、NSArrayから適切なUIImageViewを返すことができます) 。

それでおしまい。写真アプリと同じように機能します。

たくさんの写真がある場合は、メモリを節約するために、2つの内部UIScrollViewsと2つのUIImagesViewsだけを使用できます。次に、それらを動的に切り替え、外側のUIScrollView内で位置を移動し、ユーザーが外側のUIScrollViewをスクロールするときに画像を変更します。少し複雑ですが、同じ原理です。

19
delany

ネイティブのPhotosアプリをいじってみましたが、単一のUIScrollViewを使用していると自信を持って言えると思います。景品はこれです。画像を拡大し、左または右に引きます。次または前の写真が表示されます。強く引っ張ると、1.0fズームで次の写真にページ移動します。反転すると、以前にズームした写真も1.0fズームに戻ります。

明らかに、私はPhotos.appを書きませんでしたが、彼らがどのようにそれをしたのかについて大げさな推測をします

  • 単一のUIScrollViewと単一のUIScrollViewDelegate
  • UIScrollViewにUIImageViewの子を設定します
  • scrollViewDidScroll:
  • 数学を行う そして、現在どのページにいるかを把握する
  • viewForZoomingInScrollView:
  • ページインデックスに応じて異なるビューを返す
  • scrollViewDidEndZooming:withView:atScale:およびオプションでコンテンツに基づいてアンチエイリアスなどを行います

あなたがそれを試してみることに決めたら、それがあなたのためにどのように機能するか教えてください。最終的にどのように機能するようになったかを知りたいです。さらに良いことに、githubに投稿してください。

6
slf

ネイティブのPhotosアプリをいじってみましたが、単一のUIScrollViewを使用していると自信を持って言えると思います。景品はこれです。画像を拡大し、左または右に引きます。次または前の写真が表示されます。強く引っ張ると、1.0fズームで次の写真にページ移動します。反転すると、以前にズームした写真も1.0fズームに戻ります。

これは間違っています。ネストされたスクロールビューを使用していますが、まったく同じ効果が得られます。いくつかのメモリ管理スキームを使用している場合(使用を開始する必要がありました...ページ番号がかなり大きい(2 scrollViewsごとに50個ずつ))、ページをトリガーしたものと同様のメカニズムを使用できます現在のページから-1ページと+1ページのズームリセットをトリガーするためにロード/アンロードします。

前の写真が消えるとすぐにAppleがこれをオフにするだろうと思う。

私が理解していないのは、ページ間でスムーズなスクロールを実現する方法です-移行の瞬間には常に非常に短いハングがあります。分からない。 NSInvocationOperationsが最初の目的でした。その後、ページビュー(イメージビューを保持)の再利用可能なビューキューを作成しました。

NSOperationQueueを1つだけ実行していますが、同時操作の最大数をいじってみました。私の考えでは、メインスレッドは競合するキュー、またはたぶん1つのキューでさえ多くのことをしようとして詰まっているということです...それでも、ハングします。

それが問題だった場合に備えて、メディアの超低品質バージョンを作成することさえ試みました。それぞれの画像が10k前後に重なっているので(これらはjpegです、気にしないでください)...あなたはそれを推測しました。ハングはまだあります。

私は以前にやったことを行い、Three20のTTPhotoViewControllerを使用することをほぼ決心しています。私はそのコードを数時間泳いで過ごしましたが、それは常に素晴らしい教育です。しかし、この時点で、このハングがどこから来たのかを本当に知りたいのですが、そうでない場合は、脳の沸騰が少ないことを考えて眠れない時間を過ごすことができます。

1
beOn

Apple使用する写真アプリのような画像ビューアをSDKに組み込みました。現在three20を使用していますが、うまく機能します。本当に必要なのは写真ビューアだけです。

0
Francois

私はそのためのコードを書いて、参照としてすることができます

  1. 現在のビューのscrollviewとimageviewを読み込みます。現在のビューの隣の画面では、imageviewのみ

  2. 現在のページの読み込み時にすべてのビューを削除してメモリを節約するため、多くの写真プロジェクトに適しています

  3. タグを使用して異なるスクロールビューを区別します

first page_xxxxslidexxxzoom

ダウンロードリンクはここをクリック

0
chings228