SORU
30 Mart 2013, CUMARTESİ


UİCollectionView bu hücreleri Yeniden Sipariş

UICollectionView akış düzeni ve yatay bir yönü göz önünde bulundurun. Varsayılan olarak, hücre yukarıdan aşağıya, sağdan sola doğru sıralanır. Bu gibi:

1 4 7 10 13 16
2 5 8 11 14 17
3 6 9 12 15 18

Benim durumumda, koleksiyon görünümü çağrı ve hücrelerin belirli bir sayıda her sayfaya sığacak şekilde tasarlanmıştır. Böylece, bir daha doğal sıralama şöyle olacaktır:

1 2 3   10 11 12
4 5 6 - 13 14 15
7 8 9   16 17 18

En basit bunu başarmak için, kendi özel düzeni uygulama kısa ne olurdu? Özellikle, UICollectionViewFlowLayout ile beleşe işlevleri (Ekle/Kaldır animasyonlar gibi) kaybetmek istemiyorum.

Ya da genel olarak, nasıl bir akış düzeni 8* *standart olarak verilen bir fonksiyonu uygulamak mı? Aynı sağdan sola bir sipariş için geçerli, örneğin olabilir.

Benim yaklaşımım şu ana kadar

Benim ilk yaklaşım UICollectionViewFlowLayout alt layoutAttributesForItemAtIndexPath: geçersiz kılmak için:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSIndexPath *reorderedIndexPath = [self reorderedIndexPathOfIndexPath:indexPath];
    UICollectionViewLayoutAttributes *layout = [super layoutAttributesForItemAtIndexPath:reorderedIndexPath];
    layout.indexPath = indexPath;
    return layout;
}

reorderedIndexPathOfIndexPath: f(n). super, çağırarak her bir element düzeni elle hesaplamak zorunda değilim.

Ayrıca, görüntülemek için hangi düzeni seçmek için kullandığı yöntemi olan layoutAttributesForElementsInRect:, geçersiz kılmak zorunda kaldım.

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *result = [NSMutableArray array];
    NSInteger sectionCount = 1;
    if ([self.collectionView.dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)])
    {
        sectionCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
    }
    for (int s = 0; s < sectionCount; s  )
    {
        NSInteger itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:s];
        for (int i = 0; i < itemCount; i  )
        {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s];
            UICollectionViewLayoutAttributes *layout = [self layoutAttributesForItemAtIndexPath:indexPath];
            if (CGRectIntersectsRect(rect, layout.frame))
            {
                [result addObject:layout];
            }
        }
    }
    return result;
}

Ben burada sadece her öğe deneyin ve eğer rect verilen içinde ise ben geri.

Eğer bu yaklaşım gitmek için bir yoldur, daha spesifik şu soru var:

  • layoutAttributesForElementsInRect: geçersiz kılma kolaylaştırmak, ya da daha verimli çalışması için herhangi bir yolu var mı?
  • Bir şey mi kaçırdım? En azından farklı sayfaları değiştirme hücreleri garip sonuçlar üretir. initialLayoutAttributesForAppearingItemAtIndexPath: finalLayoutAttributesForDisappearingItemAtIndexPath: ilgili olduğunu sanıyorum ama sorunu tam olarak tespit edemiyorum.
  • Benim durumumda, her sayfanın sütun ve satır sayısına bağlıdır. UICollectionViewFlowLayout, hardcoding kısa gelen bu bilgileri ayıklamak için herhangi bir şekilde kendimi var mı? Koleksiyon görüntülemek sınırları ile querying layoutAttributesForElementsInRect: düşündüm, ve satır ve sütunları deducing, ama bu da yetersiz geliyor.

CEVAP
9 NİSAN 2013, Salı


Eğer soru hakkında çok düşündüm ve şu düşünceler geldi:

Bu FlowLayout sınıflara, reformlar konusunda son derece kararlıyız ve Yeniden Sipariş hücreleri için en etkili yol olarak ve akış düzeni animasyonlar kullanmak gibi görünüyor. Ve yaklaşım, iki önemli şeyin dışında çalışır:

  1. Hadi sadece 2 hücreleri ile toplama bir görünümü var ve 9 hücreleri içerebilir, böylece sayfa tasarladık. İlk hücre orijinal akışı gibi görünümü sol üst köşesinde konumlandırılmış, olacak düzen. İkinci hücre, ancak, ekranın üst kısmında konumlandırılmış olmalıdır ve dizin yolu [0, 1] vardır. Dizin yolu olurdu yeniden [0, 3] (yer olacağını orijinal akış düzeni hücre dizin yolu). Ve senin layoutAttributesForItemAtIndexPath geçersiz olur mesaj gibi [super layoutAttributesForItemAtIndexPath:[0, 3]] olur mu nil nesne, çünkü orada sadece 2 hücre: [0,0] ve [0,1]. Ve bu son sayfa için problem olabilir.
  2. Olsa bile uygulayabilirsiniz disk belleği davranış tarafından geçersiz kılma targetContentOffsetForProposedContentOffset:withScrollingVelocity: ve el ile ayarlama özellikleri gibi itemSize, minimumLineSpacing minimumInteritemSpacing çok iş yapmak, öğeleri simetrik, tanımlamak için disk belleği sınırlar.

İstediğin bir akış düzeni artık olmadığı için, senin için düzeni çok uygulama hazırlanıyor akışını sınıflara ben thnik,. Ama gelin birlikte bir düşünelim. Sorularınıza gelince:

  • layoutAttributesForElementsInRect: geçersiz kılma orijinal apple uygulama tam olarak nasıl, bunu kolaylaştırmak için bir yolu yoktur. Bu durumda olsa da, olabilir düşünün şu: eğer 3 satır öğeleri sayfa başına ve çerçeve maddenin ilk satır kesiştiği rect çerçeve, sonra (eğer tüm maddeler aynı boyut) Kare ikinci ve üçüncü satır öğeleri kesiştiği bu rect.
  • pardon, ikinci sorunuzu anlamadım
  • yeniden düzenleme işlevi bu gibi görünüyor benim durumumda: (tamsayısatır sayısı her sayfada sütun/satır=sütun)

f(n) = (n % a2) (a - 1)(sütun - satır) a2(n / a2); col = (n % 2) % a; satır = (n % a2) / a;

Bu soruya cevap, akış düzeni bu sayı her parçanın boyutuna bağlı olarak sütun için sütun değişebilir, çünkü her sütun nasıl hiçbir fikri yok. Ayrıca kaydırma konumuna bağlı olduğundan, her sayfada sütun sayısı ile ilgili bir şey olabilir ve aynı zamanda değişebilir. layoutAttributesForElementsInRect ama bu da sadece bir hücre, kısmi görünür yer alacak sorgulama daha iyi bir yolu yoktur. Beri hücreleri eşit boyutu, olabilir teorik olarak öğrenmek kaç satır var koleksiyonunuzu görmek ile yatay kaydırma yönü: ile başlayan yineleme her hücre sayımı ve kırılma durumunda onların frame.origin.x değiştirir.

Bu yüzden, bence, amacına ulaşmak için iki seçeneğiniz vardır:

  1. Alt 34**. Çok iş tüm bu yöntemleri uygulamak gibi görünüyor, ama etkili bir yoldur. Örneğin itemSize, itemsInOneRow gibi özelliklere sahip olabilir. Daha sonra kolayca bulmak için bir formül hesaplamak için, her çerçeve maddenin esas numarası (en iyi şekilde yapmak prepareLayout ve mağaza tüm çerçeveleri dizi, böylece cann erişim çerçeve gerekir layoutAttributesForItemAtIndexPath). layoutAttributesForItemAtIndexPath, layoutAttributesForItemsInRect collectionViewContentSize uygulama çok basit olacaktır. initialLayoutAttributesForAppearingItemAtIndexPath finalLayoutAttributesForDisappearingItemAtIndexPath sadece 0.0 alfa özniteliği ayarlayabilirsiniz. Standart akış düzeni iş animasyonlar. Bu uygulamak olabilir *geçersiz kılma "disk belleği davranış".

  2. Akış düzeni ile bir görünüm koleksiyonu, pagingEnabled = YES yatay kaydırma yönü ve madde boyutu ekran boyutuna eşit yapmayı düşünün. Ekran boyutu başına bir öğe. Her hücre için bir ofset ile dikey akış düzeni ve aynı veri toplama görüş olarak kaynak ile ama küme olarak yeni bir görünüm koleksiyonu ayarlayabilirsiniz. O zaman bütün toplama manzaralı 9 blok içeren (ya da her neyse) standart yaklaşım ile her hücre yeniden yerine hücreleri yeniden çünkü çok verimli. Tüm animasyonlar düzgün çalışması gerekir.

Here örnek bir proje düzeni sınıflara yaklaşım kullanarak indirebilirsiniz. (#2)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • cosmicrocketman

    cosmicrocket

    17 NİSAN 2006
  • SDSARG3

    SDSARG3

    14 Mart 2009
  • TheSalband Rai

    TheSalband R

    11 NİSAN 2011