Aracılığıyla paylaş


Xamarin.iOS'ta Koleksiyon Görünümleri

Koleksiyon Görünümleri, içeriğin rastgele düzenler kullanılarak görüntülenmesine izin verir. Bunlar, kutudan kolayca kılavuz benzeri düzenler oluşturmaya olanak sağlarken, özel düzenleri de destekler.

Sınıfında bulunan UICollectionView Koleksiyon Görünümleri, iOS 6'da düzenleri kullanarak ekranda birden çok öğe sunmayı sağlayan yeni bir kavramdır. Öğeleri oluşturmak ve bu öğelerle etkileşim kurmak için öğesine UICollectionView veri sağlamaya yönelik desenler, iOS geliştirmede yaygın olarak kullanılan temsilci ve veri kaynağı desenlerini izler.

Ancak Koleksiyon Görünümleri, kendisinden bağımsız UICollectionView bir düzen alt sistemiyle çalışır. Bu nedenle, yalnızca farklı bir düzen sağlamak koleksiyon görünümünün sunumunu kolayca değiştirebilir.

iOS, bir kılavuz gibi çizgi tabanlı düzenlerin ek çalışma olmadan oluşturulmasına izin veren adlı UICollectionViewFlowLayout bir düzen sınıfı sağlar. Ayrıca, hayal edebileceğiniz herhangi bir sunuya izin veren özel düzenler de oluşturulabilir.

UICollectionView Temel Bilgileri

UICollectionView sınıfı üç farklı öğeden oluşur:

  • Hücreler – Her öğe için veri temelli görünümler
  • Ek Görünümler : Bir bölümle ilişkilendirilmiş veri temelli görünümler.
  • Dekorasyon Görünümleri – Düzen tarafından oluşturulan veri temelli olmayan görünümler

Cells

Hücreler, koleksiyon görünümü tarafından sunulan veri kümesindeki tek bir öğeyi temsil eden nesnelerdir. Her hücre, aşağıdaki şekilde gösterildiği gibi üç farklı görünümden oluşan sınıfın bir örneğidir UICollectionViewCell :

Her hücre, burada gösterildiği gibi üç farklı görünümden oluşur

sınıfı, UICollectionViewCell bu görünümlerin her biri için aşağıdaki özelliklere sahiptir:

  • ContentView – Bu görünüm, hücrenin sunduğu içeriği içerir. Ekranın en üst z düzeninde işlenir.
  • SelectedBackgroundView – Hücreler, seçim için yerleşik desteğe sahiptir. Bu görünüm, bir hücrenin seçildiğini görsel olarak belirtmek için kullanılır. Bir hücre seçildiğinde hemen altında ContentView işlenir.
  • BackgroundView – Hücreler, tarafından BackgroundView sunulan bir arka plan da görüntüleyebilir. Bu görünüm altında SelectedBackgroundView işlenir.

ve BackgroundView SelectedBackgroundViewdeğerinden ContentView küçük BackgroundView olacak şekilde ayarlayarak, içeriği görsel olarak çerçeveleme amacıyla kullanılabilirkenSelectedBackgroundView, aşağıda gösterildiği gibi bir hücre seçildiğinde görüntülenir:

Farklı hücre öğeleri

Yukarıdaki ekran görüntüsündeki Hücreler, aşağıdaki kodda gösterildiği gibi sırasıyla öğesinden UICollectionViewCell SelectedBackgroundView devralınarak ve BackgroundView ayarlanarak ContentViewoluşturulur:

public class AnimalCell : UICollectionViewCell
{
        UIImageView imageView;

        [Export ("initWithFrame:")]
        public AnimalCell (CGRect frame) : base (frame)
        {
            BackgroundView = new UIView{BackgroundColor = UIColor.Orange};

            SelectedBackgroundView = new UIView{BackgroundColor = UIColor.Green};

            ContentView.Layer.BorderColor = UIColor.LightGray.CGColor;
            ContentView.Layer.BorderWidth = 2.0f;
            ContentView.BackgroundColor = UIColor.White;
            ContentView.Transform = CGAffineTransform.MakeScale (0.8f, 0.8f);

            imageView = new UIImageView (UIImage.FromBundle ("placeholder.png"));
            imageView.Center = ContentView.Center;
            imageView.Transform = CGAffineTransform.MakeScale (0.7f, 0.7f);

            ContentView.AddSubview (imageView);
        }

        public UIImage Image {
            set {
                imageView.Image = value;
            }
        }
}

Ek Görünümler

Tamamlayıcı Görünümler, bir UICollectionViewöğesinin her bölümüyle ilişkili bilgileri sunan görünümlerdir. Hücreler gibi Ek Görünümler de veri temellidir. Hücreler bir veri kaynağındaki öğe verilerini sunduğunda, Tamamlayıcı Görünümler kitap raflarındaki kitap kategorileri veya bir müzik kitaplığındaki müzik türü gibi bölüm verilerini sunar.

Örneğin, aşağıdaki şekilde gösterildiği gibi, belirli bir bölümün üst bilgisini sunmak için Ek Görünüm kullanılabilir:

Burada gösterildiği gibi, belirli bir bölümün üst bilgisini sunmak için kullanılan Ek Görünüm

Ek Görünüm kullanmak için öncelikle yöntemine ViewDidLoad kaydedilmesi gerekir:

CollectionView.RegisterClassForSupplementaryView (typeof(Header), UICollectionElementKindSection.Header, headerId);

Ardından, görünümün kullanılarak GetViewForSupplementaryElementdöndürülmesi gerekir, kullanılarak DequeueReusableSupplementaryViewoluşturulur ve öğesinden UICollectionReusableViewdevralır. Aşağıdaki kod parçacığı, yukarıdaki ekran görüntüsünde gösterilen SupplementaryView'ı oluşturur:

public override UICollectionReusableView GetViewForSupplementaryElement (UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath)
        {
            var headerView = (Header)collectionView.DequeueReusableSupplementaryView (elementKind, headerId, indexPath);
            headerView.Text = "Supplementary View";
            return headerView;
        }

Ek Görünümler yalnızca üst bilgi ve alt bilgilerden daha geneldir. Koleksiyon görünümünde herhangi bir yere konumlandırılabilir ve herhangi bir görünümden oluşabilir ve bu da görünümlerini tamamen özelleştirilebilir hale getirir.

Dekorasyon Görünümleri

Dekorasyon Görünümleri, içinde UICollectionViewgörüntülenebilen tamamen görsel görünümlerdir. Hücreler ve Ek Görünümler'in aksine, bunlar veri temelli değildir. Bunlar her zaman bir düzenin alt sınıfında oluşturulur ve daha sonra içeriğin düzeni olarak değişebilir. Örneğin, dekorasyon görünümü aşağıda gösterildiği gibi içindeki içerikle UICollectionViewbirlikte kayan bir arka plan görünümü sunmak için kullanılabilir:

Kırmızı arka planlı Dekorasyon Görünümü

Aşağıdaki kod parçacığı, samples CircleLayout sınıfında arka planı kırmızı olarak değiştirir:

public class MyDecorationView : UICollectionReusableView
 {
   [Export ("initWithFrame:")]
   public MyDecorationView (CGRect frame) : base (frame)
   {
     BackgroundColor = UIColor.Red;
   }
 }

Veri Kaynağı

ve gibi iOS'un diğer bölümlerinde olduğu gibi UITableView MKMapViewUICollectionView, verilerini sınıfı aracılığıyla Xamarin.iOS'ta kullanıma sunulan bir veri kaynağındanUICollectionViewDataSource alır. Bu sınıf aşağıdakilere içerik UICollectionView sağlamakla sorumludur:

  • Cells : Yönteminden GetCell döndürülür.
  • Ek Görünümler – Yöntemden GetViewForSupplementaryElement döndürülür.
  • Bölüm sayısı – Yöntemden NumberOfSections döndürülür. Uygulanmadıysa varsayılan olarak 1 olur.
  • Bölüm başına öğe sayısı – Yöntemden GetItemsCount döndürüldü.

UICollectionViewController

Kolaylık sağlamak UICollectionViewController için sınıfı kullanılabilir. Bu, hem bir sonraki bölümde ele alınan temsilci hem de görünümü için UICollectionView veri kaynağı olacak şekilde otomatik olarak yapılandırılır.

gibiUITableViewUICollectionView, sınıfı yalnızca ekrandaki öğeler için Hücreleri almak için veri kaynağını çağırır. Ekrandan aşağı kaydıran hücreler, aşağıdaki görüntüde gösterildiği gibi yeniden kullanmak üzere bir kuyruğa yerleştirilir:

Ekranı kaydıran hücreler burada gösterildiği gibi yeniden kullanmak üzere bir kuyruğa yerleştirilir

ve ile UICollectionView UITableViewhücre yeniden kullanımı basitleştirildi. Hücreler sisteme kaydedildiğinden, yeniden kullanım kuyruğunda bulunmayan bir Hücreyi artık doğrudan veri kaynağında oluşturmanız gerekmez. Hücreyi yeniden kullanma kuyruğundan çıkarmak için çağrı yapılırken Bir Hücre kullanılamıyorsa, iOS kaydedilen türe veya nib'ye göre otomatik olarak oluşturur. Aynı teknik Ek Görünümler için de kullanılabilir.

Örneğin, sınıfını kaydeden AnimalCell aşağıdaki kodu göz önünde bulundurun:

static NSString animalCellId = new NSString ("AnimalCell");
CollectionView.RegisterClassForCell (typeof(AnimalCell), animalCellId);

Öğesi ekranda olduğundan bir UICollectionView hücreye ihtiyaç duyduğunda, veri kaynağının UICollectionView GetCell yöntemini çağırır. Bunun UITableView ile nasıl çalıştığına benzer şekilde, bu yöntem de bu durumda bir sınıf olacak olan yedekleme verilerinden bir AnimalCell Hücreyi yapılandırmaktan sorumludur.

Aşağıdaki kod, örneğini GetCell döndüren uygulamasını AnimalCell gösterir:

public override UICollectionViewCell GetCell (UICollectionView collectionView, Foundation.NSIndexPath indexPath)
{
        var animalCell = (AnimalCell)collectionView.DequeueReusableCell (animalCellId, indexPath);

        var animal = animals [indexPath.Row];

        animalCell.Image = animal.Image;

        return animalCell;
}

çağrısı DequeReusableCell , hücrenin yeniden kullanım kuyruğundan kuyruğa alınmadığı veya kuyrukta bir hücre yoksa çağrısında CollectionView.RegisterClassForCellkaydedilen türe göre oluşturulduğu yerdir.

Bu durumda, sınıfı kaydederek AnimalCell iOS dahili olarak yeni AnimalCell bir oluşturur ve bir hücrenin kuyruğa alınıp kuyruğa alınıp hayvan sınıfında yer alan görüntüyle yapılandırıldığında ve görüntülenmesi UICollectionViewiçin döndürülür.

Temsilci

sınıfı, UICollectionView içindeki UICollectionViewiçerikle etkileşimi desteklemek için türünde UICollectionViewDelegate bir temsilci kullanır. Bu, şunların denetlenmesini sağlar:

  • Hücre Seçimi : Bir hücrenin seçili olup olmadığını belirler.
  • Hücre Vurgulama – Bir hücreye dokunulduğunu belirler.
  • Hücre Menüleri – Uzun bir basma hareketine yanıt olarak bir hücre için görüntülenen menü.

Veri kaynağında olduğu gibi, UICollectionViewController varsayılan olarak için temsilci UICollectionViewolarak yapılandırılır.

HighLighting Hücresi

Bir Hücreye basıldığında, hücre vurgulanmış duruma geçirilir ve kullanıcı hücreden parmağını kaldırana kadar seçilmez. Bu, hücrenin gerçekten seçilmeden önce görünümünde geçici bir değişiklik yapılmasını sağlar. Seçimden sonra Hücre'ler SelectedBackgroundView görüntülenir. Aşağıdaki şekilde, seçim gerçekleşmeden hemen önce vurgulanan durum gösterilmektedir:

Bu şekilde, seçim gerçekleşmeden hemen önce vurgulanan durum gösterilir

Vurgulama ItemHighlighted uygulamak için ve ItemUnhighlighted yöntemleri UICollectionViewDelegate kullanılabilir. Örneğin, aşağıdaki kod, yukarıdaki resimde gösterildiği gibi Hücre vurgulandığında sarı bir arka plan ContentView ve vurgulanmamışsa beyaz bir arka plan uygular:

public override void ItemHighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
        var cell = collectionView.CellForItem(indexPath);
        cell.ContentView.BackgroundColor = UIColor.Yellow;
}

public override void ItemUnhighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
        var cell = collectionView.CellForItem(indexPath);
        cell.ContentView.BackgroundColor = UIColor.White;
}

Seçimi Devre Dışı Bırakma

seçimi içinde UICollectionViewvarsayılan olarak etkindir. Seçimi devre dışı bırakmak için, aşağıda gösterildiği gibi geçersiz kılın ShouldHighlightItem ve false değerini döndürin:

public override bool ShouldHighlightItem (UICollectionView collectionView, NSIndexPath indexPath)
{
        return false;
}

Vurgulama devre dışı bırakıldığında, hücre seçme işlemi de devre dışı bırakılır. Ayrıca, doğrudan seçimi denetleyen bir ShouldSelectItem yöntem de vardır, ancak uygulanırsa ve false ShouldSelectItem döndürürse ShouldHighlightItem çağrılmaz.

ShouldSelectItem , uygulanmadığında ShouldHighlightItem seçimin öğe bazında açılmasını veya kapatılmasını sağlar. Ayrıca uygulanırsa ve true döndürürken ShouldSelectItem false döndürürseShouldHighlightItem, seçim olmadan vurgulama sağlar.

Hücre Menüleri

içindeki UICollectionView her Hücre isteğe bağlı olarak kesilmesine, kopyalanıp yapıştırılmasına izin veren bir menü gösterebilme özelliğine sahiptir. Hücrede düzenleme menüsü oluşturmak için:

  1. Öğenin bir menü göstermesi gerekiyorsa geçersiz kıl ShouldShowMenu ve true değerini döndür.
  2. Öğenin gerçekleştirebileceği her eylem için, kesme, kopyalama veya yapıştırma işlemlerinin herhangi biri olacak şekilde geçersiz kılın CanPerformAction ve true değerini döndürin.
  3. Yapıştırma işlemini düzenleme, kopyalama işlemini gerçekleştirmek için geçersiz kılın PerformAction .

Aşağıdaki ekran görüntüsünde bir hücreye uzun basıldığında menü gösterilir:

Bu ekran görüntüsü, bir hücreye uzun basıldığında menüyü gösterir

Düzen

UICollectionView , tüm öğelerinin (Hücreler, Tamamlayıcı Görünümler ve Dekorasyon Görünümleri) kendilerinden UICollectionView bağımsız olarak yönetilmesini sağlayan bir düzen sistemini destekler. Bir uygulama, düzen sistemini kullanarak bu makalede gördüğümüz kılavuz benzeri düzenleri destekleyebilir ve özel düzenler sağlayabilir.

Düzen Temelleri

içindeki UICollectionView düzenler öğesinden UICollectionViewLayoutdevralan bir sınıfta tanımlanır. Düzen uygulaması, içindeki her öğe için düzen özniteliklerini oluşturmaktan UICollectionViewsorumludur. Düzen oluşturmanın iki yolu vardır:

  • Yerleşik UICollectionViewFlowLayout kullanın.
  • öğesinden UICollectionViewLayout devralarak özel bir düzen sağlayın.

Akış Düzeni

sınıfı, UICollectionViewFlowLayout gördüğümüz gibi Hücreler kılavuzunda içerik düzenlemeye uygun bir çizgi tabanlı düzen sağlar.

Akış düzeni kullanmak için:

  • örneğini UICollectionViewFlowLayout oluşturun:
var layout = new UICollectionViewFlowLayout ();
  • örneğini oluşturucusna UICollectionView geçirin:
simpleCollectionViewController = new SimpleCollectionViewController (layout);

Bir kılavuzdaki içeriği düzenlerken gereken tek şey budur. Ayrıca, yönlendirme değiştiğinde UICollectionViewFlowLayout , aşağıda gösterildiği gibi içeriği uygun şekilde yeniden düzenleme tutamaçları:

Yönlendirme değişiklikleri örneği

Bölüm Başlangıcı

çevresinde UIContentViewbiraz alan sağlamak için düzenlerin türünde UIEdgeInsetsbir SectionInset özelliği vardır. Örneğin, aşağıdaki kod tarafından yerleştirildiğinde öğesinin UIContentView her bölümü çevresinde 50 piksellik bir UICollectionViewFlowLayoutarabellek sağlar:

var layout = new UICollectionViewFlowLayout ();
layout.SectionInset = new UIEdgeInsets (50,50,50,50);

Bu, aşağıda gösterildiği gibi bölümün çevresinde aralıklara neden olur:

Burada gösterildiği gibi bölümün etrafındaki aralık

UICollectionViewFlowLayout alt sınıfı oluşturma

Doğrudan kullanmak UICollectionViewFlowLayout için yayında, bir satır boyunca içeriğin düzenini daha fazla özelleştirmek için alt sınıfa da eklenebilir. Örneğin, bu, Aşağıda gösterildiği gibi Hücreleri kılavuza sarmamayan, bunun yerine yatay kaydırma efektine sahip tek bir satır oluşturan bir düzen oluşturmak için kullanılabilir:

Yatay kaydırma efektine sahip tek satır

Bunu alt sınıflamayla UICollectionViewFlowLayout uygulamak için şunlar gerekir:

  • Düzenin kendisine veya oluşturucudaki düzendeki tüm öğelere uygulanan düzen özelliklerini başlatma.
  • geçersiz kılma ShouldInvalidateLayoutForBoundsChange , değişikliklerin sınırları olduğunda hücrelerin düzeninin UICollectionView yeniden hesaplanması için true değerini döndürür. Bu, bu durumda en ortadaki hücreye uygulanan dönüştürme kodunun kaydırma sırasında uygulandığından emin olmak için kullanılır.
  • Kaydırma durduğunda en ortadaki hücrenin UICollectionView ortasına tutturmak için geçersiz TargetContentOffset kılma.
  • Bir dizi UICollectionViewLayoutAttributes döndürmek için geçersiz kılınıyorLayoutAttributesForElementsInRect. Her UICollectionViewLayoutAttribute öğe, , ve Transform3D gibi özellikler de dahil olmak üzere belirli bir öğenin nasıl düzenlenip düzenlendiği hakkında Center Size ZIndex bilgi içerir.

Aşağıdaki kodda böyle bir uygulama gösterilmektedir:

using System;
using CoreGraphics;
using Foundation;
using UIKit;
using CoreGraphics;
using CoreAnimation;

namespace SimpleCollectionView
{
  public class LineLayout : UICollectionViewFlowLayout
  {
    public const float ITEM_SIZE = 200.0f;
    public const int ACTIVE_DISTANCE = 200;
    public const float ZOOM_FACTOR = 0.3f;

    public LineLayout ()
    {
      ItemSize = new CGSize (ITEM_SIZE, ITEM_SIZE);
      ScrollDirection = UICollectionViewScrollDirection.Horizontal;
            SectionInset = new UIEdgeInsets (400,0,400,0);
      MinimumLineSpacing = 50.0f;
    }

    public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
    {
      return true;
    }

    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
    {
      var array = base.LayoutAttributesForElementsInRect (rect);
            var visibleRect = new CGRect (CollectionView.ContentOffset, CollectionView.Bounds.Size);

      foreach (var attributes in array) {
        if (attributes.Frame.IntersectsWith (rect)) {
          float distance = (float)(visibleRect.GetMidX () - attributes.Center.X);
          float normalizedDistance = distance / ACTIVE_DISTANCE;
          if (Math.Abs (distance) < ACTIVE_DISTANCE) {
            float zoom = 1 + ZOOM_FACTOR * (1 - Math.Abs (normalizedDistance));
            attributes.Transform3D = CATransform3D.MakeScale (zoom, zoom, 1.0f);
            attributes.ZIndex = 1;
          }
        }
      }
      return array;
    }

    public override CGPoint TargetContentOffset (CGPoint proposedContentOffset, CGPoint scrollingVelocity)
    {
      float offSetAdjustment = float.MaxValue;
      float horizontalCenter = (float)(proposedContentOffset.X + (this.CollectionView.Bounds.Size.Width / 2.0));
      CGRect targetRect = new CGRect (proposedContentOffset.X, 0.0f, this.CollectionView.Bounds.Size.Width, this.CollectionView.Bounds.Size.Height);
      var array = base.LayoutAttributesForElementsInRect (targetRect);
      foreach (var layoutAttributes in array) {
        float itemHorizontalCenter = (float)layoutAttributes.Center.X;
        if (Math.Abs (itemHorizontalCenter - horizontalCenter) < Math.Abs (offSetAdjustment)) {
          offSetAdjustment = itemHorizontalCenter - horizontalCenter;
        }
      }
            return new CGPoint (proposedContentOffset.X + offSetAdjustment, proposedContentOffset.Y);
    }

  }
}

Özel Düzen

'yi kullanmaya UICollectionViewFlowLayoutek olarak, düzenleri doğrudan öğesinden UICollectionViewLayoutdevralınarak da tamamen özelleştirilebilir.

Geçersiz kılınacak temel yöntemler şunlardır:

  • PrepareLayout – Düzen işlemi boyunca kullanılacak ilk geometrik hesaplamaları gerçekleştirmek için kullanılır.
  • CollectionViewContentSize – İçeriği görüntülemek için kullanılan alanın boyutunu döndürür.
  • LayoutAttributesForElementsInRect – Daha önce gösterilen UICollectionViewFlowLayout örneğinde olduğu gibi, bu yöntem her öğenin nasıl düzenlenmesiyle ilgili bilgi sağlamak için UICollectionView kullanılır. Ancak, özel bir düzen oluştururken öğesinden UICollectionViewFlowLayout farklı olarak, öğeleri istediğiniz gibi konumlandırabilirsiniz.

Örneğin, aynı içerik aşağıda gösterildiği gibi döngüsel bir düzende sunulabilir:

Burada gösterildiği gibi dairesel bir özel düzen

Düzenlerle ilgili güçlü olan şey, kılavuz benzeri düzenden yatay kaydırma düzenine geçmek ve daha sonra bu döngüsel düzene geçmek için yalnızca düzenin değiştirilmesi gerekir UICollectionView . içindeki UICollectionViewhiçbir şey, temsilci veya veri kaynağı kodunda hiçbir değişiklik olmaz.

iOS 9'daki değişiklikler

iOS 9'da koleksiyon görünümü (UICollectionView) artık yeni bir varsayılan hareket tanıyıcı ve birkaç yeni destekleyici yöntem ekleyerek öğelerin kutu dışına sürüklenerek yeniden sıralanmasını destekliyor.

Bu yeni yöntemleri kullanarak, koleksiyon görünümünüzde yeniden sıralamak için sürüklemeyi kolayca uygulayabilir ve yeniden sıralama işleminin herhangi bir aşamasında öğelerin görünümünü özelleştirme seçeneğine sahip olabilirsiniz.

Yeniden sıralama işlemi örneği

Bu makalede, bir Xamarin.iOS uygulamasında sürükle-yeniden sıralama uygulama ve iOS 9'un koleksiyon görünümü denetiminde yaptığı diğer değişikliklerden bazılarını inceleyeceğiz:

Öğelerin Yeniden Sıralanması

Yukarıda belirtildiği gibi, iOS 9'da koleksiyon görünümünde yapılan en önemli değişikliklerden biri, kolay sürükleyerek yeniden sıralama işlevselliğinin kullanıma alınmasıydı.

iOS 9'da koleksiyon görünümüne yeniden sıralama eklemenin en hızlı yolu kullanmaktır UICollectionViewController. Koleksiyon görünümü denetleyicisi artık koleksiyondaki öğeleri yeniden sıralamak için sürüklemeyi destekleyen standart bir hareket tanıyıcısı ekleyen bir InstallsStandardGestureForInteractiveMovement özelliğe sahiptir. Varsayılan değer olduğundantrue, yalnızca sürükle ve yeniden sıralamayı desteklemek için sınıfının yöntemini UICollectionViewDataSource uygulamanız MoveItem gerekir. Örneğin:

public override void MoveItem (UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
  // Reorder our list of items
  ...
}

Basit Yeniden Sıralama Örneği

Hızlı bir örnek olarak, yeni bir Xamarin.iOS projesi başlatın ve Main.storyboard dosyasını düzenleyin. Bir'i UICollectionViewController tasarım yüzeyine sürükleyin:

UICollectionViewController Ekleme

Koleksiyon Görünümü'nü seçin (Bunu belge ana hattından yapmak en kolayı olabilir). Özellikler Bölmesi'nin düzen sekmesinde, aşağıdaki ekran görüntüsünde gösterildiği gibi aşağıdaki boyutları ayarlayın:

  • Hücre Boyutu: Genişlik – 60 | Yükseklik – 60
  • Üst Bilgi Boyutu: Genişlik – 0 | Yükseklik – 0
  • Alt Bilgi Boyutu: Genişlik – 0 | Yükseklik – 0
  • En Düşük Aralık: Hücreler için – 8 | Satırlar için – 8
  • Bölüm Kümeleri: Üst – 16 | Alt – 16 | Sol – 16 | Sağ – 16

Koleksiyon Görünümü boyutlarını ayarlama

Ardından, varsayılan Hücreyi düzenleyin:

  • Arka plan rengini mavi olarak değiştirme
  • Hücrenin başlığı olarak davranacak bir etiket ekleme
  • Yeniden kullanım tanımlayıcısını hücre olarak ayarlama

Varsayılan Hücreyi düzenleme

Boyutu değiştikçe Etiketi hücrenin içinde ortalanmış olarak tutmak için kısıtlamalar ekleyin:

CollectionViewCell'in Özellik Bölmesi'nde Sınıfı olarak TextCollectionViewCellayarlayın:

Sınıfı TextCollectionViewCell olarak ayarlama

Koleksiyon Yeniden Kullanılabilir Görünümünü olarak Cellayarlayın:

Koleksiyon Yeniden Kullanılabilir Görünümünü Hücre olarak ayarlama

Son olarak Etiket'i seçin ve olarak adlandırın TextLabel:

name label TextLabel

sınıfını TextCollectionViewCell düzenleyin ve aşağıdaki özellikleri ekleyin:

using System;
using Foundation;
using UIKit;

namespace CollectionView
{
  public partial class TextCollectionViewCell : UICollectionViewCell
  {
    #region Computed Properties
    public string Title {
      get { return TextLabel.Text; }
      set { TextLabel.Text = value; }
    }
    #endregion

    #region Constructors
    public TextCollectionViewCell (IntPtr handle) : base (handle)
    {
    }
    #endregion
  }
}

Text Burada etiketin özelliği, koddan ayarlanabilmesi için hücrenin başlığı olarak gösterilir.

Projeye yeni bir C# sınıfı ekleyin ve olarak adlandırın WaterfallCollectionSource. Dosyayı düzenleyin ve aşağıdaki gibi görünmesini sağlayın:

using System;
using Foundation;
using UIKit;
using System.Collections.Generic;

namespace CollectionView
{
  public class WaterfallCollectionSource : UICollectionViewDataSource
  {
    #region Computed Properties
    public WaterfallCollectionView CollectionView { get; set;}
    public List<int> Numbers { get; set; } = new List<int> ();
    #endregion

    #region Constructors
    public WaterfallCollectionSource (WaterfallCollectionView collectionView)
    {
      // Initialize
      CollectionView = collectionView;

      // Init numbers collection
      for (int n = 0; n < 100; ++n) {
        Numbers.Add (n);
      }
    }
    #endregion

    #region Override Methods
    public override nint NumberOfSections (UICollectionView collectionView) {
      // We only have one section
      return 1;
    }

    public override nint GetItemsCount (UICollectionView collectionView, nint section) {
      // Return the number of items
      return Numbers.Count;
    }

    public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
    {
      // Get a reusable cell and set {~~it's~>its~~} title from the item
      var cell = collectionView.DequeueReusableCell ("Cell", indexPath) as TextCollectionViewCell;
      cell.Title = Numbers [(int)indexPath.Item].ToString();

      return cell;
    }

    public override bool CanMoveItem (UICollectionView collectionView, NSIndexPath indexPath) {
      // We can always move items
      return true;
    }

    public override void MoveItem (UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
    {
      // Reorder our list of items
      var item = Numbers [(int)sourceIndexPath.Item];
      Numbers.RemoveAt ((int)sourceIndexPath.Item);
      Numbers.Insert ((int)destinationIndexPath.Item, item);
    }
    #endregion
  }
}

Bu sınıf, koleksiyon görünümümüzün veri kaynağı olacak ve koleksiyondaki her hücre için bilgi sağlayacaktır. yönteminin MoveItem koleksiyondaki öğelerin yeniden sıralanmasını sağlamak için uygulandığına dikkat edin.

Projeye başka bir yeni C# sınıfı ekleyin ve olarak adlandırın WaterfallCollectionDelegate. Bu dosyayı düzenleyin ve aşağıdaki gibi görünmesini sağlayın:

using System;
using Foundation;
using UIKit;
using System.Collections.Generic;

namespace CollectionView
{
  public class WaterfallCollectionDelegate : UICollectionViewDelegate
  {
    #region Computed Properties
    public WaterfallCollectionView CollectionView { get; set;}
    #endregion

    #region Constructors
    public WaterfallCollectionDelegate (WaterfallCollectionView collectionView)
    {

      // Initialize
      CollectionView = collectionView;

    }
    #endregion

    #region Overrides Methods
    public override bool ShouldHighlightItem (UICollectionView collectionView, NSIndexPath indexPath) {
      // Always allow for highlighting
      return true;
    }

    public override void ItemHighlighted (UICollectionView collectionView, NSIndexPath indexPath)
    {
      // Get cell and change to green background
      var cell = collectionView.CellForItem(indexPath);
      cell.ContentView.BackgroundColor = UIColor.FromRGB(183,208,57);
    }

    public override void ItemUnhighlighted (UICollectionView collectionView, NSIndexPath indexPath)
    {
      // Get cell and return to blue background
      var cell = collectionView.CellForItem(indexPath);
      cell.ContentView.BackgroundColor = UIColor.FromRGB(164,205,255);
    }
    #endregion
  }
}

Bu, koleksiyon görünümümüz için temsilci görevi görür. Kullanıcı koleksiyon görünümünde hücreyle etkileşim kurarken hücreyi vurgulamak için yöntemler geçersiz kılındı.

Projeye son bir C# sınıfı ekleyin ve olarak adlandırın WaterfallCollectionView. Bu dosyayı düzenleyin ve aşağıdaki gibi görünmesini sağlayın:

using System;
using UIKit;
using System.Collections.Generic;
using Foundation;

namespace CollectionView
{
  [Register("WaterfallCollectionView")]
  public class WaterfallCollectionView : UICollectionView
  {

    #region Constructors
    public WaterfallCollectionView (IntPtr handle) : base (handle)
    {
    }
    #endregion

    #region Override Methods
    public override void AwakeFromNib ()
    {
      base.AwakeFromNib ();

      // Initialize
      DataSource = new WaterfallCollectionSource(this);
      Delegate = new WaterfallCollectionDelegate(this);

    }
    #endregion
  }
}

DataSource Yukarıda oluşturduğumuz ve Delegate öğesinin, koleksiyon görünümü görsel taslaktan (veya .xib dosyasından) oluşturulduğunda ayarlandığına dikkat edin.

Main.storyboard dosyasını yeniden düzenleyin ve koleksiyon görünümünü seçip Özellikler'e geçin. Sınıfı yukarıda tanımladığımız özel WaterfallCollectionView sınıf olarak ayarlayın:

Kullanıcı arabiriminde yaptığınız değişiklikleri kaydedin ve uygulamayı çalıştırın. Kullanıcı listeden bir öğe seçer ve öğeyi yeni bir konuma sürüklerse, diğer öğeler öğenin yolundan uzaklaştıkça otomatik olarak animasyon ekler. Kullanıcı öğeyi yeni bir konuma düşürdüğünüzde bu konuma bağlı kalır. Örneğin:

Öğeyi yeni bir konuma sürükleme örneği

Özel Hareket Tanıyıcı kullanma

kullanamadığınız UICollectionViewController ve normal UIViewControllerbir kullanmanız gereken durumlarda veya sürükle ve bırak hareketi üzerinde daha fazla denetim sahibi olmak istiyorsanız, kendi özel Hareket Tanıyıcınızı oluşturabilir ve Görünüm yüklendiğinde bunu Koleksiyon Görünümü'ne ekleyebilirsiniz. Örneğin:

public override void ViewDidLoad ()
{
  base.ViewDidLoad ();

  // Create a custom gesture recognizer
  var longPressGesture = new UILongPressGestureRecognizer ((gesture) => {

    // Take action based on state
    switch(gesture.State) {
    case UIGestureRecognizerState.Began:
      var selectedIndexPath = CollectionView.IndexPathForItemAtPoint(gesture.LocationInView(View));
      if (selectedIndexPath !=null) {
        CollectionView.BeginInteractiveMovementForItem(selectedIndexPath);
      }
      break;
    case UIGestureRecognizerState.Changed:
      CollectionView.UpdateInteractiveMovementTargetPosition(gesture.LocationInView(View));
      break;
    case UIGestureRecognizerState.Ended:
      CollectionView.EndInteractiveMovement();
      break;
    default:
      CollectionView.CancelInteractiveMovement();
      break;
    }

  });

  // Add the custom recognizer to the collection view
  CollectionView.AddGestureRecognizer(longPressGesture);
}

Burada, sürükleme işlemini uygulamak ve denetlemek için koleksiyon görünümüne eklenen birkaç yeni yöntem kullanıyoruz:

  • BeginInteractiveMovementForItem - Taşıma işleminin başlangıcını işaretler.
  • UpdateInteractiveMovementTargetPosition - Öğenin konumu güncelleştirildikçe gönderilir.
  • EndInteractiveMovement - Öğe taşıma işleminin sonunu işaretler.
  • CancelInteractiveMovement - Taşıma işlemini iptal eden kullanıcıyı işaretler.

Uygulama çalıştırıldığında, sürükleme işlemi koleksiyon görünümüyle birlikte gelen varsayılan sürükleme hareketi tanıyıcısı gibi çalışır.

Özel Düzenler ve Yeniden Sıralama

iOS 9'da, bir koleksiyon görünümünde sürükle ve yeniden sıralama ve özel düzenlerle çalışmak için birkaç yeni yöntem eklenmiştir. Bu özelliği keşfetmek için koleksiyona özel bir düzen ekleyelim.

İlk olarak, projeye adlı WaterfallCollectionLayout yeni bir C# sınıfı ekleyin. Düzenleyin ve aşağıdaki gibi görünmesini sağlayın:

using System;
using Foundation;
using UIKit;
using System.Collections.Generic;
using CoreGraphics;

namespace CollectionView
{
  [Register("WaterfallCollectionLayout")]
  public class WaterfallCollectionLayout : UICollectionViewLayout
  {
    #region Private Variables
    private int columnCount = 2;
    private nfloat minimumColumnSpacing = 10;
    private nfloat minimumInterItemSpacing = 10;
    private nfloat headerHeight = 0.0f;
    private nfloat footerHeight = 0.0f;
    private UIEdgeInsets sectionInset = new UIEdgeInsets(0, 0, 0, 0);
    private WaterfallCollectionRenderDirection itemRenderDirection = WaterfallCollectionRenderDirection.ShortestFirst;
    private Dictionary<nint,UICollectionViewLayoutAttributes> headersAttributes = new Dictionary<nint, UICollectionViewLayoutAttributes>();
    private Dictionary<nint,UICollectionViewLayoutAttributes> footersAttributes = new Dictionary<nint, UICollectionViewLayoutAttributes>();
    private List<CGRect> unionRects = new List<CGRect>();
    private List<nfloat> columnHeights = new List<nfloat>();
    private List<UICollectionViewLayoutAttributes> allItemAttributes = new List<UICollectionViewLayoutAttributes>();
    private List<List<UICollectionViewLayoutAttributes>> sectionItemAttributes = new List<List<UICollectionViewLayoutAttributes>>();
    private nfloat unionSize = 20;
    #endregion

    #region Computed Properties
    [Export("ColumnCount")]
    public int ColumnCount {
      get { return columnCount; }
      set {
        WillChangeValue ("ColumnCount");
        columnCount = value;
        DidChangeValue ("ColumnCount");

        InvalidateLayout ();
      }
    }

    [Export("MinimumColumnSpacing")]
    public nfloat MinimumColumnSpacing {
      get { return minimumColumnSpacing; }
      set {
        WillChangeValue ("MinimumColumnSpacing");
        minimumColumnSpacing = value;
        DidChangeValue ("MinimumColumnSpacing");

        InvalidateLayout ();
      }
    }

    [Export("MinimumInterItemSpacing")]
    public nfloat MinimumInterItemSpacing {
      get { return minimumInterItemSpacing; }
      set {
        WillChangeValue ("MinimumInterItemSpacing");
        minimumInterItemSpacing = value;
        DidChangeValue ("MinimumInterItemSpacing");

        InvalidateLayout ();
      }
    }

    [Export("HeaderHeight")]
    public nfloat HeaderHeight {
      get { return headerHeight; }
      set {
        WillChangeValue ("HeaderHeight");
        headerHeight = value;
        DidChangeValue ("HeaderHeight");

        InvalidateLayout ();
      }
    }

    [Export("FooterHeight")]
    public nfloat FooterHeight {
      get { return footerHeight; }
      set {
        WillChangeValue ("FooterHeight");
        footerHeight = value;
        DidChangeValue ("FooterHeight");

        InvalidateLayout ();
      }
    }

    [Export("SectionInset")]
    public UIEdgeInsets SectionInset {
      get { return sectionInset; }
      set {
        WillChangeValue ("SectionInset");
        sectionInset = value;
        DidChangeValue ("SectionInset");

        InvalidateLayout ();
      }
    }

    [Export("ItemRenderDirection")]
    public WaterfallCollectionRenderDirection ItemRenderDirection {
      get { return itemRenderDirection; }
      set {
        WillChangeValue ("ItemRenderDirection");
        itemRenderDirection = value;
        DidChangeValue ("ItemRenderDirection");

        InvalidateLayout ();
      }
    }
    #endregion

    #region Constructors
    public WaterfallCollectionLayout ()
    {
    }

    public WaterfallCollectionLayout(NSCoder coder) : base(coder) {

    }
    #endregion

    #region Public Methods
    public nfloat ItemWidthInSectionAtIndex(int section) {

      var width = CollectionView.Bounds.Width - SectionInset.Left - SectionInset.Right;
      return (nfloat)Math.Floor ((width - ((ColumnCount - 1) * MinimumColumnSpacing)) / ColumnCount);
    }
    #endregion

    #region Override Methods
    public override void PrepareLayout ()
    {
      base.PrepareLayout ();

      // Get the number of sections
      var numberofSections = CollectionView.NumberOfSections();
      if (numberofSections == 0)
        return;

      // Reset collections
      headersAttributes.Clear ();
      footersAttributes.Clear ();
      unionRects.Clear ();
      columnHeights.Clear ();
      allItemAttributes.Clear ();
      sectionItemAttributes.Clear ();

      // Initialize column heights
      for (int n = 0; n < ColumnCount; n++) {
        columnHeights.Add ((nfloat)0);
      }

      // Process all sections
      nfloat top = 0.0f;
      var attributes = new UICollectionViewLayoutAttributes ();
      var columnIndex = 0;
      for (nint section = 0; section < numberofSections; ++section) {
        // Calculate section specific metrics
        var minimumInterItemSpacing = (MinimumInterItemSpacingForSection == null) ? MinimumColumnSpacing :
          MinimumInterItemSpacingForSection (CollectionView, this, section);

        // Calculate widths
        var width = CollectionView.Bounds.Width - SectionInset.Left - SectionInset.Right;
        var itemWidth = (nfloat)Math.Floor ((width - ((ColumnCount - 1) * MinimumColumnSpacing)) / ColumnCount);

        // Calculate section header
        var heightHeader = (HeightForHeader == null) ? HeaderHeight :
          HeightForHeader (CollectionView, this, section);

        if (heightHeader > 0) {
          attributes = UICollectionViewLayoutAttributes.CreateForSupplementaryView (UICollectionElementKindSection.Header, NSIndexPath.FromRowSection (0, section));
          attributes.Frame = new CGRect (0, top, CollectionView.Bounds.Width, heightHeader);
          headersAttributes.Add (section, attributes);
          allItemAttributes.Add (attributes);

          top = attributes.Frame.GetMaxY ();
        }

        top += SectionInset.Top;
        for (int n = 0; n < ColumnCount; n++) {
          columnHeights [n] = top;
        }

        // Calculate Section Items
        var itemCount = CollectionView.NumberOfItemsInSection(section);
        List<UICollectionViewLayoutAttributes> itemAttributes = new List<UICollectionViewLayoutAttributes> ();

        for (nint n = 0; n < itemCount; n++) {
          var indexPath = NSIndexPath.FromRowSection (n, section);
          columnIndex = NextColumnIndexForItem (n);
          var xOffset = SectionInset.Left + (itemWidth + MinimumColumnSpacing) * (nfloat)columnIndex;
          var yOffset = columnHeights [columnIndex];
          var itemSize = (SizeForItem == null) ? new CGSize (0, 0) : SizeForItem (CollectionView, this, indexPath);
          nfloat itemHeight = 0.0f;

          if (itemSize.Height > 0.0f && itemSize.Width > 0.0f) {
            itemHeight = (nfloat)Math.Floor (itemSize.Height * itemWidth / itemSize.Width);
          }

          attributes = UICollectionViewLayoutAttributes.CreateForCell (indexPath);
          attributes.Frame = new CGRect (xOffset, yOffset, itemWidth, itemHeight);
          itemAttributes.Add (attributes);
          allItemAttributes.Add (attributes);
          columnHeights [columnIndex] = attributes.Frame.GetMaxY () + MinimumInterItemSpacing;
        }
        sectionItemAttributes.Add (itemAttributes);

        // Calculate Section Footer
        nfloat footerHeight = 0.0f;
        columnIndex = LongestColumnIndex();
        top = columnHeights [columnIndex] - MinimumInterItemSpacing + SectionInset.Bottom;
        footerHeight = (HeightForFooter == null) ? FooterHeight : HeightForFooter(CollectionView, this, section);

        if (footerHeight > 0) {
          attributes = UICollectionViewLayoutAttributes.CreateForSupplementaryView (UICollectionElementKindSection.Footer, NSIndexPath.FromRowSection (0, section));
          attributes.Frame = new CGRect (0, top, CollectionView.Bounds.Width, footerHeight);
          footersAttributes.Add (section, attributes);
          allItemAttributes.Add (attributes);
          top = attributes.Frame.GetMaxY ();
        }

        for (int n = 0; n < ColumnCount; n++) {
          columnHeights [n] = top;
        }
      }

      var i =0;
      var attrs = allItemAttributes.Count;
      while(i < attrs) {
        var rect1 = allItemAttributes [i].Frame;
        i = (int)Math.Min (i + unionSize, attrs) - 1;
        var rect2 = allItemAttributes [i].Frame;
        unionRects.Add (CGRect.Union (rect1, rect2));
        i++;
      }

    }

    public override CGSize CollectionViewContentSize {
      get {
        if (CollectionView.NumberOfSections () == 0) {
          return new CGSize (0, 0);
        }

        var contentSize = CollectionView.Bounds.Size;
        contentSize.Height = columnHeights [0];
        return contentSize;
      }
    }

    public override UICollectionViewLayoutAttributes LayoutAttributesForItem (NSIndexPath indexPath)
    {
      if (indexPath.Section >= sectionItemAttributes.Count) {
        return null;
      }

      if (indexPath.Item >= sectionItemAttributes [indexPath.Section].Count) {
        return null;
      }

      var list = sectionItemAttributes [indexPath.Section];
      return list [(int)indexPath.Item];
    }

    public override UICollectionViewLayoutAttributes LayoutAttributesForSupplementaryView (NSString kind, NSIndexPath indexPath)
    {
      var attributes = new UICollectionViewLayoutAttributes ();

      switch (kind) {
      case "header":
        attributes = headersAttributes [indexPath.Section];
        break;
      case "footer":
        attributes = footersAttributes [indexPath.Section];
        break;
      }

      return attributes;
    }

    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
    {
      var begin = 0;
      var end = unionRects.Count;
      List<UICollectionViewLayoutAttributes> attrs = new List<UICollectionViewLayoutAttributes> ();

      for (int i = 0; i < end; i++) {
        if (rect.IntersectsWith(unionRects[i])) {
          begin = i * (int)unionSize;
        }
      }

      for (int i = end - 1; i >= 0; i--) {
        if (rect.IntersectsWith (unionRects [i])) {
          end = (int)Math.Min ((i + 1) * (int)unionSize, allItemAttributes.Count);
          break;
        }
      }

      for (int i = begin; i < end; i++) {
        var attr = allItemAttributes [i];
        if (rect.IntersectsWith (attr.Frame)) {
          attrs.Add (attr);
        }
      }

      return attrs.ToArray();
    }

    public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
    {
      var oldBounds = CollectionView.Bounds;
      return (newBounds.Width != oldBounds.Width);
    }
    #endregion

    #region Private Methods
    private int ShortestColumnIndex() {
      var index = 0;
      var shortestHeight = nfloat.MaxValue;
      var n = 0;

      // Scan each column for the shortest height
      foreach (nfloat height in columnHeights) {
        if (height < shortestHeight) {
          shortestHeight = height;
          index = n;
        }
        ++n;
      }

      return index;
    }

    private int LongestColumnIndex() {
      var index = 0;
      var longestHeight = nfloat.MinValue;
      var n = 0;

      // Scan each column for the shortest height
      foreach (nfloat height in columnHeights) {
        if (height > longestHeight) {
          longestHeight = height;
          index = n;
        }
        ++n;
      }

      return index;
    }

    private int NextColumnIndexForItem(nint item) {
      var index = 0;

      switch (ItemRenderDirection) {
      case WaterfallCollectionRenderDirection.ShortestFirst:
        index = ShortestColumnIndex ();
        break;
      case WaterfallCollectionRenderDirection.LeftToRight:
        index = ColumnCount;
        break;
      case WaterfallCollectionRenderDirection.RightToLeft:
        index = (ColumnCount - 1) - ((int)item / ColumnCount);
        break;
      }

      return index;
    }
    #endregion

    #region Events
    public delegate CGSize WaterfallCollectionSizeDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, NSIndexPath indexPath);
    public delegate nfloat WaterfallCollectionFloatDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, nint section);
    public delegate UIEdgeInsets WaterfallCollectionEdgeInsetsDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, nint section);

    public event WaterfallCollectionSizeDelegate SizeForItem;
    public event WaterfallCollectionFloatDelegate HeightForHeader;
    public event WaterfallCollectionFloatDelegate HeightForFooter;
    public event WaterfallCollectionEdgeInsetsDelegate InsetForSection;
    public event WaterfallCollectionFloatDelegate MinimumInterItemSpacingForSection;
    #endregion
  }
}

Bu, koleksiyon görünümüne özel iki sütun, şelale türü düzeni sağlamak için kullanılabilir. Kod, bu sınıftaki WillChangeValue hesaplanan özelliklerimiz için veri bağlama sağlamak üzere Anahtar-Değer Kodlaması (ve DidChangeValue yöntemleri aracılığıyla) kullanır.

Ardından, öğesini düzenleyin WaterfallCollectionSource ve aşağıdaki değişiklikleri ve eklemeleri yapın:

private Random rnd = new Random();
...

public List<nfloat> Heights { get; set; } = new List<nfloat> ();
...

public WaterfallCollectionSource (WaterfallCollectionView collectionView)
{
  // Initialize
  CollectionView = collectionView;

  // Init numbers collection
  for (int n = 0; n < 100; ++n) {
    Numbers.Add (n);
    Heights.Add (rnd.Next (0, 100) + 40.0f);
  }
}

Bu, listede görüntülenecek öğelerin her biri için rastgele bir yükseklik oluşturur.

Ardından sınıfını WaterfallCollectionView düzenleyin ve aşağıdaki yardımcı özelliğini ekleyin:

public WaterfallCollectionSource Source {
  get { return (WaterfallCollectionSource)DataSource; }
}

Bu sayede özel düzenden veri kaynağımıza (ve öğe yüksekliklerine) ulaşmak kolaylaşır.

Son olarak, görünüm denetleyicisini düzenleyin ve aşağıdaki kodu ekleyin:

public override void AwakeFromNib ()
{
  base.AwakeFromNib ();

  var waterfallLayout = new WaterfallCollectionLayout ();

  // Wireup events
  waterfallLayout.SizeForItem += (collectionView, layout, indexPath) => {
    var collection = collectionView as WaterfallCollectionView;
    return new CGSize((View.Bounds.Width-40)/3,collection.Source.Heights[(int)indexPath.Item]);
  };

  // Attach the custom layout to the collection
  CollectionView.SetCollectionViewLayout(waterfallLayout, false);
}

Bu, özel düzenimizin bir örneğini oluşturur, olayı her öğenin boyutunu sağlayacak şekilde ayarlar ve yeni düzeni koleksiyon görünümümüze ekler.

Xamarin.iOS uygulamasını yeniden çalıştırırsak koleksiyon görünümü artık aşağıdaki gibi görünür:

Koleksiyon görünümü şimdi şöyle görünür

Öğeleri daha önce olduğu gibi sürükleyerek yeniden sıralamaya devam edebiliriz, ancak artık öğeler bırakıldığında boyutları yeni konumlarına uyacak şekilde değişir.

Koleksiyon Görünümü Değişiklikleri

Aşağıdaki bölümlerde, iOS 9 tarafından koleksiyon görünümünde her sınıfta yapılan değişikliklere ayrıntılı bir bakış sağlayacağız.

UICollectionView

iOS 9 sınıfında aşağıdaki değişiklikler veya eklemeler yapılmıştır UICollectionView :

  • BeginInteractiveMovementForItem – Sürükleme işleminin başlangıcını işaretler.
  • CancelInteractiveMovement – Kullanıcının bir sürükleme işlemini iptal ettiğini koleksiyon görünümüne bildirir.
  • EndInteractiveMovement – Kullanıcının bir sürükleme işlemini tamamlamış olduğunu koleksiyon görünümüne bildirir.
  • GetIndexPathsForVisibleSupplementaryElements – Koleksiyon görünümü bölümündeki üst bilgi veya alt bilginin değerini döndürür indexPath .
  • GetSupplementaryView – Verilen üst bilgiyi veya alt bilgiyi döndürür.
  • GetVisibleSupplementaryViews – Tüm görünür üst bilgi ve alt bilgilerin listesini döndürür.
  • UpdateInteractiveMovementTargetPosition – Kullanıcının sürükleme işlemi sırasında bir öğeyi taşıdığını veya taşıdığını koleksiyon görünümüne bildirir.

UICollectionViewController

iOS 9'da sınıfına UICollectionViewController aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • InstallsStandardGestureForInteractiveMovementtrue– Sürükle ve yeniden sıralamayı otomatik olarak destekleyen yeni Hareket Tanıyıcı kullanılır.
  • CanMoveItem – Belirli bir öğenin yeniden sürüklenip sıralanamadığını koleksiyon görünümüne bildirir.
  • GetTargetContentOffset – Belirli bir koleksiyon görünümü öğesinin uzaklığını almak için kullanılır.
  • GetTargetIndexPathForMove – Sürükleme işlemi için belirli bir öğenin öğesini alır indexPath .
  • MoveItem – Listedeki belirli bir öğenin sırasını taşır.

UICollectionViewDataSource

iOS 9'da sınıfına UICollectionViewDataSource aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • CanMoveItem – Belirli bir öğenin yeniden sürüklenip sıralanamadığını koleksiyon görünümüne bildirir.
  • MoveItem – Listedeki belirli bir öğenin sırasını taşır.

UICollectionViewDelegate

iOS 9'da sınıfına UICollectionViewDelegate aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • GetTargetContentOffset – Belirli bir koleksiyon görünümü öğesinin uzaklığını almak için kullanılır.
  • GetTargetIndexPathForMove – Sürükleme işlemi için belirli bir öğenin öğesini alır indexPath .

UICollectionViewFlowLayout

iOS 9'da sınıfına UICollectionViewFlowLayout aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • SectionFootersPinToVisibleBounds – Bölüm altbilgilerini görünür koleksiyon görünümü sınırlarına yapıştırır.
  • SectionHeadersPinToVisibleBounds – Bölüm üst bilgilerini görünür koleksiyon görünümü sınırlarına yapıştırır.

UICollectionViewLayout

iOS 9'da sınıfına UICollectionViewLayout aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • GetInvalidationContextForEndingInteractiveMovementOfItems – Kullanıcı sürükleme işlemini tamamladığında veya iptal ettiğinde, sürükleme işleminin sonundaki geçersizleştirme bağlamını döndürür.
  • GetInvalidationContextForInteractivelyMovingItems – Bir sürükleme işleminin başındaki geçersizleştirme bağlamını döndürür.
  • GetLayoutAttributesForInteractivelyMovingItem – Bir öğe sürüklenirken belirli bir öğenin Düzen Özniteliklerini alır.
  • GetTargetIndexPathForInteractivelyMovingItem – Bir öğe sürüklenirken verilen noktadaki öğenin değerini döndürür indexPath .

UICollectionViewLayoutAttributes

iOS 9'da sınıfına UICollectionViewLayoutAttributes aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • CollisionBoundingPath – Sürükleme işlemi sırasında iki öğenin çarpışma yolunu döndürür.
  • CollisionBoundsType – Sürükleme işlemi sırasında oluşan çarpışma türünü ( UIDynamicItemCollisionBoundsTypeolarak) döndürür.

UICollectionViewLayoutInvalidationContext

iOS 9'da sınıfına UICollectionViewLayoutInvalidationContext aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • InteractiveMovementTarget – Sürükleme işleminin hedef öğesini döndürür.
  • PreviousIndexPathsForInteractivelyMovingItems – Yeniden sıralama işleminin sürüklenmesinde yer alan diğer öğelerin sayısını döndürür indexPaths .
  • TargetIndexPathsForInteractivelyMovingItems – Sürükle ve indexPaths yeniden sıralama işleminin sonucu olarak yeniden sıralanacak öğelerin sayısını döndürür.

UICollectionViewSource

iOS 9'da sınıfına UICollectionViewSource aşağıdaki değişiklikler veya eklemeler yapılmıştır:

  • CanMoveItem – Belirli bir öğenin yeniden sürüklenip sıralanamadığını koleksiyon görünümüne bildirir.
  • GetTargetContentOffset – Sürükle ve yeniden sıralama işlemiyle taşınacak öğelerin uzaklıklarını döndürür.
  • GetTargetIndexPathForMove – Sürükle ve indexPath yeniden sıralama işlemi sırasında taşınacak öğenin değerini döndürür.
  • MoveItem – Listedeki belirli bir öğenin sırasını taşır.

Özet

Bu makalede, iOS 9'daki koleksiyon görünümlerinde yapılan değişiklikler ele alınmıştır ve bunların Xamarin.iOS'ta nasıl uygulandığı açıklanmıştır. Koleksiyon görünümünde basit bir yeniden sıralamaya sürükle eyleminin uygulanması ele alınmıştır; sürükle ve yeniden sıralama ile özel Bir Hareket Tanıyıcı kullanma; ve sürükleyerek yeniden sıralamanın özel koleksiyon görünümü düzenini nasıl etkilediğini gösterir.