UICollectionView Horizontal Paging ortalanmadı

Her hücrede görünümün boyutunda bir yatay kaydırma collectionView var. Ben toplama görünümünde sayfa, hücre tarafından sayfa yok. Hücreler ekranın merkezinde değil. Düzeltmeyi denemek için bir sürü şey denedim ve hiç şansım olmadı. İşte problemin bir videosu: https://www.youtube.com/watch?v=tXsxWelk16w Herhangi bir fikir?

25
İşe yaramalıydı. Ayrıca minimumLineSpacing değerini 0 olarak ayarladığınızdan emin olun (varsayılan 10).
katma yazar rdelmar, kaynak
Sayfanın genişliği, koleksiyon görünümünün genişliği ile belirlenir. Hücre boyutunu nasıl ayarlıyorsun? Koleksiyon görünümünün boyutuna mı yoksa denetimine mi ayarlıyorsunuz?
katma yazar rdelmar, kaynak
@rdelmar, koleksiyon görünümünün boyutuna göre ayarlama
katma yazar mlevi, kaynak

10 cevap

Öğeler arasındaki boşlukları kaldırın. Yatay kaydırma koleksiyonu görünümü için minimum satır aralığı 0 olarak ayarlayın. Bunu arayüz oluşturucu ile veya UICollectionViewDelegateFlowLayout protokolü yöntemiyle yapabilirsiniz:

- (CGFloat)collectionView:(UICollectionView *)collectionView 
                   layout:(UICollectionViewLayout *)collectionViewLayout 
        minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 0;    
}

enter image description here

Diğer bir yol, öğeleriniz arasındaki yatay boşluk değeri için hücrenin genişliğini collectionView'in genişliğinden daha az yapmaktır. Sonra, öğeler arasında yatay boşluğun yarısına eşit sol ve sağ ek parçalara sahip bölüm iç metinleri ekleyin. Örneğin, minimum satır aralığı 10

- (CGFloat)collectionView:(UICollectionView *)collectionView
                   layout:(UICollectionViewLayout *)collectionViewLayout
        minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 10;
}

- (CGSize)collectionView:(UICollectionView *)collectionView 
                  layout:(UICollectionViewLayout *)collectionViewLayout 
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(collectionView.frame.size.width - 10, collectionView.frame.size.height);
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView 
                        layout:(UICollectionViewLayout *)collectionViewLayout 
        insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(0, 5, 0, 5);
}

enter image description here

Ve üçüncü yol: collectionView kaydırma işlemini scrollViewDidEndDecelerating: yönteminde değiştirin:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView == self.collectionView) {
        CGPoint currentCellOffset = self.collectionView.contentOffset;
        currentCellOffset.x += self.collectionView.frame.size.width/2;
        NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:currentCellOffset];
        [self.collectionView scrollToItemAtIndexPath:indexPath
                                    atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                            animated:YES];
    }
}

enter image description here

88
katma
İlk seçenek basit ve mükemmel çalışıyor! Herhangi birinin Swift 2. * delege işlevi istemesi durumunda: func collectionView (collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex bölümü: Int) -> CGFloat {return 0}
katma yazar Nathaniel, kaynak
Koleksiyon görünümünün büyüklüğünde hücrelerin, aralarındaki yatay boşlukların ve ortalanmış sayfaların olamaz. Bir seçim yap.
katma yazar Vlad Che, kaynak
Başka bir yol: hücrenin genişliğini = (collectionView width - minimumLineSpacing) yapın ve sol ve sağ insets ile minimum minimumLineSpacing/2 eşit bölüm ekleri ekleyin.
katma yazar Vlad Che, kaynak
Bu çözümle cevabımı güncelledim.
katma yazar Vlad Che, kaynak
Mükemmel!! İkinci seçenek benim için hile yaptı :) Paylaşım için teşekkürler.
katma yazar Edouard Barbier, kaynak
Merhaba, cevabımı aşağıda kontrol edin. Apple'dan iki satır. @VladimirKravchenko
katma yazar lastcc, kaynak
Teşekkürler, çözümünüz mükemmel çalışıyor.
katma yazar Ankit Jain, kaynak

Demo here in Swift 3: https://github.com/damienromito/CollectionViewCustom

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) {

    let pageWidth = Float(itemWidth + itemSpacing)
    let targetXContentOffset = Float(targetContentOffset.pointee.x)
    let contentWidth = Float(collectionView!.contentSize.width  )
    var newPage = Float(self.pageControl.currentPage)

    if velocity.x == 0 {
        newPage = floor( (targetXContentOffset - Float(pageWidth)/2)/Float(pageWidth)) + 1.0
    } else {
        newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)
        if newPage < 0 {
            newPage = 0
        }
        if (newPage > contentWidth/pageWidth) {
            newPage = ceil(contentWidth/pageWidth) - 1.0
        }
    }
    self.pageControl.currentPage = Int(newPage)
    let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)
    targetContentOffset.pointee = point
}

Swift 4:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) {

    let pageWidth = Float(itemWidth + itemSpacing)
    let targetXContentOffset = Float(targetContentOffset.pointee.x)
    let contentWidth = Float(collectionView!.contentSize.width  )
    var newPage = Float(self.pageControl.currentPage)

    if velocity.x == 0 {
        newPage = floor( (targetXContentOffset - Float(pageWidth)/2)/Float(pageWidth)) + 1.0
    } else {
        newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)
        if newPage < 0 {
            newPage = 0
        }
        if (newPage > contentWidth/pageWidth) {
            newPage = ceil(contentWidth/pageWidth) - 1.0
        }
    }

    self.pageControl.currentPage = Int(newPage)
    let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)
    targetContentOffset.pointee = point
}
24
katma
Çok teşekkür ederim, çekicilik gibi çalışır
katma yazar Mandeep Singh, kaynak
Kayma hızını nasıl kontrol ederim? Onu artırmak istiyorum.
katma yazar Anirudha Mahale, kaynak
Swift 4 kodu burada bulunuyor./& hellip;
katma yazar Nik Kov, kaynak
En basit çözüm !!!!!!!! Teşekkürler....
katma yazar Pratik Mistry, kaynak
Çekicilik gibi çalışır, teşekkürler!
katma yazar xavi.pedrals, kaynak
eserleri harika. Teşekkürler ....
katma yazar Ansal Antony, kaynak

@ Vlad-che'nın hızlıca kabul ettiği cevap:

extension GoodsViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {

        return 10
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let frameSize = collectionView.frame.size
        return CGSize(width: frameSize.width - 10, height: frameSize.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

        return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }
}
7
katma

Hücreler arasında boşluk bırakan collectionView çerçevesinin daha küçük hücrelere sahip olması, kullanıcının diğer taraflara kaydırılacağını ve bu sayede UX için büyük bir kazanç olduğunu gösteren bir ipucu olmasını sağlar. Ancak sayfaların merkezlenmesi, kullanıcı kaydırdıkça giderek artan ve dengelenen her hücre ile beklendiği gibi çalışmaz. İyi çalışmak için aşağıdakileri buldum. Her bir hücredeki merkezleme/yapışma animasyonu neredeyse görünmezdir, çünkü yalnızca collectionView kaydırmasının, başka bir öğeye hızlıca kaydırmak için collectionView ile sarsmak yerine doğal olarak sona ereceği ince ayardır code> indexPath . sectionInset özelliğinin, hücrenin içeren çerçeve kenarlarına yapışmamasına izin verecek kadar büyük ayarlanmış olması hala önemlidir. Ayrıca, hücreler arasında boşluklar olduğundan, hedef bir indexPath değerine inebilir ve bu da collectionView öğesinin başa dönmesine neden olur. Bu dengelemeyi biraz düzelttim ve sonra tekrar denedim, ancak burada farklı yaklaşımlar alınabilir.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset
{
    //Ensure the scrollview is the collectionview we care about
    if (scrollView == self.collectionView) {

       //Find cell closest to the frame centre with reference from the targetContentOffset.
        CGPoint frameCentre = self.collectionView.center;
        CGPoint targetOffsetToCentre = CGPointMake((* targetContentOffset).x + frameCentre.x, (* targetContentOffset).y + frameCentre.y);

        NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre];

            //Check for "edgecase" that the target will land between cells and then find a close neighbour to prevent scrolling to index {0,0}.
        while (!indexPath) {
            targetOffsetToCentre.x += ((UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout).minimumInteritemSpacing;
            indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre];
        }

       //Find the centre of the target cell
        CGPoint centreCellPoint = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath].center;

       //Calculate the desired scrollview offset with reference to desired target cell centre.
        CGPoint desiredOffset = CGPointMake(centreCellPoint.x - frameCentre.x, centreCellPoint.y - frameCentre.y);
        *targetContentOffset = desiredOffset;
    }
}
3
katma

Swift 3 solution based on @Santos's answer, for use if if you have a regular horizontally paging collection view without a page control like Paolo was using in his Swift 3 example.

Bunu, özel bir UICollectionViewFlowLayout animatörüne sahip bir yatay sayfalama hücresi tam ekran hücrelerinin dönmeyi bitiremediği ve ofset yaptığı bir sorunu çözmek için kullandım, böylece bir tam ekran hücre çerçevesinin kenarları, toplama görünümünün sınırlarından giderek yatay bir şekilde ayrıldı; kaydırdığınız gibi (paylaşılan OP videodaki gibi).

 func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) {

   //Ensure the scrollview is the one on the collectionView we care are working with 
    if (scrollView == self.collectionView) {

       //Find cell closest to the frame centre with reference from the targetContentOffset.
        let frameCenter: CGPoint = self.collectionView.center
        var targetOffsetToCenter: CGPoint = CGPoint(x: targetContentOffset.pointee.x + frameCenter.x, y: targetContentOffset.pointee.y + frameCenter.y)
        var indexPath: IndexPath? = self.collectionView.indexPathForItem(at: targetOffsetToCenter)

       //Check for "edge case" where the target will land right between cells and then next neighbor to prevent scrolling to index {0,0}.
        while indexPath == nil {
            targetOffsetToCenter.x += 10
            indexPath = self.collectionView.indexPathForItem(at: targetOffsetToCenter)
        }
       //safe unwrap to make sure we found a valid index path
        if let index = indexPath { 
           //Find the centre of the target cell
            if let centerCellPoint: CGPoint = collectionView.layoutAttributesForItem(at: index)?.center {

               //Calculate the desired scrollview offset with reference to desired target cell centre.
                let desiredOffset: CGPoint = CGPoint(x: centerCellPoint.x - frameCenter.x, y: centerCellPoint.y - frameCenter.y)
                targetContentOffset.pointee = desiredOffset
            }
        }
    }
}
2
katma

Swift 3

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if scrollView == self.collectionView {
            var currentCellOffset = self.collectionView.contentOffset
            currentCellOffset.x += self.collectionView.frame.width/2
            if let indexPath = self.collectionView.indexPathForItem(at: currentCellOffset) {
              self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
            }
        }
    }
2
katma
İşe yarıyor ama sayfadan sayfaya her taşındığınızda garip bir görsel efekt görüyorsunuz.
katma yazar xavi.pedrals, kaynak

Apple Resmi Kılavuzlarından az önce gördüğüm kod ve Örnek Kod:

AssetViewController.swift:

self.collectionView?.isPagingEnabled = true
self.collectionView?.frame = view.frame.insetBy(dx: -20.0, dy: 0.0)
0
katma
Bu kod, koleksiyon görünümünü, içerik yalnızca ekran kenarlarındayken ekrandan dışarı çıkacak şekilde genişletir.
katma yazar lastcc, kaynak
çok açık ve akıllı, çekicilik gibi çalışır.
katma yazar lastcc, kaynak

Hücreleri merkezde tutmak için satır aralığını kaldırmak için Swift 4 çözümü

public func collectionView(_ collectionView: UICollectionView, layout 
collectionViewLayout: UICollectionViewLayout, 
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}
0
katma

After having a similar issue, I fixed mine by realizing that when using horizontal scrolling the height is now the width and the width is now the height because the default is set for vertical scrolling. Try switching the values and see if that helps. https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html

0
katma

Swift 3.0 kendi UICollectionViewFlowLayout'ınızı ayarlayın

let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = UIScreen.main.bounds.width
layout.itemSize = CGSize(width: width, height: 154)
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.scrollDirection = .horizontal
collectionView?.collectionViewLayout = layout
0
katma