2016-03-23 6 views
2

詳細thisチュートリアルの後に、ページングのUIScrollViewで、ScrollViewを実装して、以前のUICollectionViewControllerからダウンロードした写真をスライドショーとして使用しました。スクロールビューがロードされると、私はこれらのものを見るので、それがうまく動作しません:Swift:PageControlでScrollViewを動作させる方法は?

enter image description here代わりenter image description hereenter image description here

、私は彼らが正しい方法、各ページに1つに表示された画像を背面にスライドさせます。または、この問題は、スライドショーで4番目の画像を取得したときに消えてしまい、その時点で次の画像がすべて正しくなり、前の画像も同様になります。最初の2枚または3枚の画像に影響する問題です。

さらにスライドショーはUICollectionViewCellから開始されていなくても、ユーザーはタップしていますが、常に最初のものから始まります。私は、問題は、私はチュートリアルから理解していないものです/***/とラインかもしれないと思い

import Foundation 
import UIKit 

class PagedScrollViewController: UIViewController, UIScrollViewDelegate { 

@IBOutlet var scrollView: UIScrollView! 
@IBOutlet var pageControl: UIPageControl! 

/* This will hold all the images to display – 1 per page. 
    It must be set from the previous view controller in prepareforsegue() method: 
    it will be the array of downloaded images for that photo gallery */ 
var pageImages:[UIImage]! 

/* position in array images of the first to be showed, i.e. the one the user has just tapped */ 
var firstToShow:Int! 

var currentImageViewForZoom:UIImageView? 

/* This will hold instances of UIImageView to display each image on its respective page. 
    It’s an array of optionals, because you’ll be loading the pages lazily (i.e. as and when you need them) 
    so you need to be able to handle nil values from the array. */ 
var pageViews:[UIImageView?] = [] 

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.scrollView.delegate = self 
    self.scrollView.maximumZoomScale = 1.0 
    self.scrollView.zoomScale = 10.0 

    self.pageControl.numberOfPages = self.pageImages.count 
    self.pageControl.currentPage = self.firstToShow 

    for _ in 0..<self.pageImages.count { 
     self.pageViews.append(nil) 
    } 

    /* The scroll view, as before, needs to know its content size. 
     Since you want a horizontal paging scroll view, you calculate the width to be the number of pages multiplied by the width of the scroll view. 
     The height of the content is the same as the height of the scroll view 
    */ 
    let pagesScrollViewSize = self.scrollView.frame.size 
    self.scrollView.contentSize = CGSize(width: pagesScrollViewSize.width * CGFloat(self.pageImages.count), 
     height: pagesScrollViewSize.height) 

    // You’re going to need some pages shown initially, so you call loadVisiblePages() 
    self.loadVisiblePages() 

} 

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { 
    return self.currentImageViewForZoom 
} 

func scrollViewDidScroll(scrollView: UIScrollView) { 
    self.loadVisiblePages() 
} 

/* 
Remember each page is a UIImageView stored in an array of optionals. 
When the view controller loads, the array is filled with nil. 
This method will load the content of each page. 

1 - If it's outside the range of what you have to display, then do nothing 

2 - If pageView is nil, then you need to create a page. So first, work out the frame for this page. 
    It’s calculated as being the same size as the scroll view, positioned at zero y offset, 
    and then offset by the width of a page multiplied by the page number in the x (horizontal) direction. 

3 - Finally, you replace the nil in the pageViews array with the view you’ve just created, 
    so that if this page was asked to load again, you would now not go into the if statement and instead do nothing, 
    since the view for the page has already been created 

*/ 
func loadPage(page: Int) { 
    if page < 0 || page >= self.pageImages.count { 
     //1 
     return 
    } 

    //2 
    if let _ = self.pageViews[page] {/*Do nothing. The view is already loaded*/} 
    else { 
     // 2 
     var frame = self.scrollView.bounds 
     frame.origin.x = frame.size.width * CGFloat(page) 
     frame.origin.y = 0.0 

     let newPageView = UIImageView(image: self.pageImages[page]) 
     newPageView.contentMode = .ScaleAspectFit 
     newPageView.frame = frame 
     self.scrollView.addSubview(newPageView) 

     // 3 
     self.pageViews[page] = newPageView 
     self.currentImageViewForZoom = newPageView 
    } 
} 

/* 
This function purges a page that was previously created via loadPage(). 
It first checks that the object in the pageViews array for this page is not nil. 
If it’s not, it removes the view from the scroll view and updates the pageViews array with nil again to indicate that this page is no longer there. 
Why bother lazy loading and purging pages, you ask? 
Well, in this example, it won’t matter too much if you load all the pages at the start, since there are only five and they won’t be large enough to eat up too much memory. 
But imagine you had 100 pages and each image was 5MB in size. That would take up 500MB of memory if you loaded all the pages at once! 
Your app would quickly exceed the amount of memory available and be killed by the operating system. 
Lazy loading means that you’ll only have a certain number of pages in memory at any given time. 
*/ 
func purgePage(page: Int) { 
    if page < 0 || page >= self.pageImages.count { 
     // If it's outside the range of what you have to display, then do nothing 
     return 
    } 

    // Remove a page from the scroll view and reset the container array 
    if let pageView = self.pageViews[page] { 
     pageView.removeFromSuperview() 
     self.pageViews[page] = nil 
    } 
} 

func loadVisiblePages() { 
    // First, determine which page is currently visible 
    let pageWidth = self.scrollView.frame.size.width 

    // floor() function will round a decimal number to the next lowest integer 
    let page = Int(floor((self.scrollView.contentOffset.x * 2.0 + pageWidth)/(pageWidth * 2.0))) /***/ 

    // Update the page control 
    self.pageControl.currentPage = page 

    // Work out which pages you want to load 
    let firstPage = page - 1 
    let lastPage = page + 1 

    // Purge anything before the first page 
    for var index = 0; index < firstPage; ++index { 
     self.purgePage(index) 
    } 

    // Load pages in our range 
    for index in firstPage...lastPage { 
     self.loadPage(index) 
    } 

    // Purge anything after the last page 
    for var index = lastPage+1; index < self.pageImages.count; ++index { 
     self.purgePage(index) 
    } 
} 
} 

:あなたはここにすべてのコードを読むことができます。

override func viewDidLayoutSubviews() { 
    self.loadVisiblePages() 
} 

を、現在の画像が正しく、次のとおりですので、ここで私は試してみました何、UPDATE、ここで探し はSO同様の記事のために、誰かがviewDidLayoutSubviews()にサブビューを作成することをお勧め

ご清聴ありがとうございました最初の3枚の画像にはそれ以上の奇妙な効果はありません。しかしなぜ?私はジュニアのiOSデベロッパーであり、これらのメソッドをオーバーライドする方法と、それらが動作する順序はまだ分かっていません。とにかく、他の画像がタップされていても、最初の画像から常に画像が表示されるという問題が残ります。常に

enter image description here

(コーナーを任さ)最初の画像別のものがタップされている場合でも表示されます。たとえば、これを見て持っています。最後に、私のコードでは、デリゲートメソッドを実装してズームを実装しましたが、動作しません。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    if (segue.identifier == "toSlideShow") { 
     let pagedScrollViewController:PagedScrollViewController = segue.destinationViewController as! PagedScrollViewController 
     pagedScrollViewController.pageImages = self.imagesDownloaded 
     pagedScrollViewController.firstToShow = self.collectionView?.indexPathsForSelectedItems()![0].row 
    } 
} 
+1

UIScrollViewでズーム機能を使用するには、スクロールビューのminimumZoomScaleを設定する必要があります。 viewDidLayoutSubviewsにコードを移動する必要がある理由は、自動レイアウトを使用しており、ビューコントローラのフレームが自動レイアウトエンジンによって変更される前にviewDidLoadが呼び出されたためです。 viewDidLoadでself.view.frameを印刷すると、通常、ストーリーボードのデフォルトサイズである0,0,600,600が表示されます。 'self.scrollView.contentSize = CGSize(width:pagesScrollViewSize.width * CGFloat(self.pageImages.count)、 height:pagesScrollViewSize.height)'を間違っています。 – beyowulf

+1

セルをタップすることによって開始されるsegueのコードをprepareForSegueにポストします。 – beyowulf

+0

@beyowulf質問したコードを追加して質問を更新しました。私はスマートフォンで編集したのでうまく整形されたと思っています。私は今オフィスにいます...本当にありがとうございます。 –

答えて

2

あなたは、スクロールビューのオフセットのと等しくなるようにオフセットを更新する必要があります:

UPDATE 2

ここでユーザーがセルをタップする前のUICollectionViewControllerからprepareForSegue()のコードですトランジション後に表示したい画像。 self.scrollView.contentOffset = CGPoint(x: pagesScrollViewSize.width * CGFloat(self.firstToShow), y: 0.0)あなたはそれのように見えるように思われる、viewDidLayoutSubviewsでこれを行うことができます:あなたが強調表示さ

override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 
     self.scrollView.delegate = self 
     self.scrollView.maximumZoomScale = 2.0 
     self.scrollView.zoomScale = 1.0 
     self.scrollView.minimumZoomScale = 0.5 

     self.pageControl.numberOfPages = self.pageImages.count 
     self.pageControl.currentPage = self.firstToShow 

     for _ in 0..<self.pageImages.count { 
      self.pageViews.append(nil) 
     } 

     /* The scroll view, as before, needs to know its content size. 
     Since you want a horizontal paging scroll view, you calculate the width to be the number of pages multiplied by the width of the scroll view. 
     The height of the content is the same as the height of the scroll view 
     */ 
     let pagesScrollViewSize = self.scrollView.frame.size 
     self.scrollView.contentSize = CGSize(width: pagesScrollViewSize.width * CGFloat(self.pageImages.count), 
      height: pagesScrollViewSize.height) 

     self.scrollView.contentOffset = CGPoint(x: pagesScrollViewSize.width * CGFloat(self.firstToShow), y: 0.0) 

     // You’re going to need some pages shown initially, so you call loadVisiblePages() 
     self.loadVisiblePages() 

    } 

行だけスクロールビューがオンになって何ページかを決定するために最も近い画像インデックスに切り捨てています。問題は、ビューコントローラにスクロールが行われていないと表示され、常に最初のイメージが表示される場合です。最初に表示したい画像を取得するには、スクロールビューのオフセットを上記のようにオフセットする必要があります。

+0

本当にありがとうございました。今私が見る最初のイメージは、タップされたイメージです。とにかく、他の画像はもうスクロールできません...スクロールしようとすると、現在の画像の一部と前または次の一部が表示され、ページが更新されません... –

関連する問題