See Also: UICollectionView Members
The MonoTouch.UIKit.UICollectionView is a container view that allows the application developer to lay out multiple items on the screen with more flexibility than is provided by a MonoTouch.UIKit.UITableView. It is a subtype of MonoTouch.UIKit.UIScrollView, so the layouts can span multiple pages. The layout used by the MonoTouch.UIKit.UICollectionView is controlled by it's UICollectionView.CollectionViewLayout property.
A MonoTouch.UIKit.UICollectionView must have a MonoTouch.UIKit.UICollectionViewLayout. The most commonly-used MonoTouch.UIKit.UICollectionViewLayout is MonoTouch.UIKit.UICollectionViewFlowLayout, which lays out its content views either horizontally or vertically until it reaches the bounds and then wraps around.
These grid-like layouts are very flexible and customizable, but because MonoTouch.UIKit.UICollectionView and MonoTouch.UIKit.UICollectionViewLayout are independent, simply providing a different MonoTouch.UIKit.UICollectionViewLayout can easily change the presentation style of the MonoTouch.UIKit.UICollectionView. The application developer can create custom layouts to support whatever layout can be imagined.
The patterns for providing data to a MonoTouch.UIKit.UICollectionView to create items and interact with those items follow the same delegation and data source patterns commonly used in iOS development.
Collection Views are more powerful than MonoTouch.UIKit.UITableViews, which are limited to a single column, but are also more complex. MonoTouch.UIKit.UITableView has certain built-in behaviors such as an editing mode, row animations, and easy-to-use headers and footers. If a MonoTouch.UIKit.UITableView satisfies the application's UI requirements, the application developer should prefer to use the MonoTouch.UIKit.UITableView.
A MonoTouch.UIKit.UICollectionView user interface involves a collaboration of different objects with different concerns:
Concern | Description | Types |
---|---|---|
Content Management | The overall contents of the user interface | MonoTouch.UIKit.UICollectionView, MonoTouch.UIKit.UICollectionViewController |
Layout | Position and layout attributes of various component views | MonoTouch.UIKit.UICollectionViewLayout, MonoTouch.UIKit.UICollectionViewLayoutAttributes, MonoTouch.UIKit.UICollectionViewUpdateItem |
Data Management | Data and event-management | MonoTouch.UIKit.UICollectionViewDataSource, MonoTouch.UIKit.UICollectionViewDelegate |
Reusable views | Define component elements of the overall MonoTouch.UIKit.UICollectionView | MonoTouch.UIKit.UICollectionViewCell, MonoTouch.UIKit.UICollectionReusableView |
A MonoTouch.UIKit.UICollectionView is made up of three different types of MonoTouch.UIKit.UIViews:
Role | Description | Type |
---|---|---|
Cells | Data-driven views, each of a single item in the data set. | MonoTouch.UIKit.UICollectionViewCell |
Supplementary views | Data-driven views, each associated with a section. For example, header and footer views. | MonoTouch.UIKit.UICollectionReusableView |
Decoration views | Non-data-driven views associated with the layout and overall view appearance. For example, the scrolling bookshelves background in the iBooks app and the Newsstand. | MonoTouch.UIKit.UICollectionReusableView |
The relationship between these three types of views is shown in the following image, based on the "Introduction to Collection Views" article. The cells are the orange-and-white rectangles and are laid out in a line. An instance of a supplementary view with a UIView.BackgroundColor of UIColor.Yellow separates sections, while a single decoration view provides a background for the entire MonoTouch.UIKit.UICollectionView.
(Background image by NASA, http://visibleearth.nasa.gov/)
The MonoTouch.UIKit.UICollectionView is designed to work with large datasets. The two major attributes of this design are the "reuse queue" for component views and the MonoTouch.UIKit.UICollectionViewDataSource interface. The reuse queue is a system-managed collection of component views that minimizes memory consumption by only allocating those views that are on-screen and a handful of "next visible" screens. The following illustration, based on a variation of the code from the "Introduction to Collection Views" sample, shows how efficient this reuse queue is: 204 views are visible but the reuse queue only consists of 217 instances of the AnimalCell subtype of MonoTouch.UIKit.UICollectionViewCell. The dataset numbers in the thousands, but the number of actually allocated view components is minimal.
Not only does the reuse queue only have a minimal number of component views, it reuses component views rather than allocating and releasing off-screen views. This helps greatly with performance, but has important consequences for the application developer:
The following code, from the "Introduction to Collection Views" sample, shows how component view types are registered and reassigned. Each component role type has an MonoTouch.Foundation.NSString identifier (for instance, the type AnimalCell, which is used for the cell role, has the identifier "AnimalCell", the others are not shown). The methods UICollectionView.RegisterClassForCell and UICollectionView.RegisterClassForSupplementaryView register the classes for the cell and supplementary view roles, while the method UICollectionViewLayout.RegisterClassForDecorationView registers the decoration view with the MonoTouch.UIKit.UICollectionViewLayout that is the MonoTouch.UIKit.UICollectionView's' UICollectionView.CollectionViewLayout property.
It is very important that you provide a constructor that takes a RectangleF argument in any subclasses that you register with UICollectionView. This is required because the classes are actually allocated by the Objective-C runtime, and you must initialize them. The following example shows the expected constructor that you should provide:
C# Example
public class AnimalCell : UICollectionViewCell { [Export ("initWithFrame:")] public AnimalCell (RectangleF frame) : base (frame) {} }
The overridden methods UICollectionViewDataSource.GetCell and UICollectionViewSource.GetViewForSupplementaryElement show the re-assignment code. The MonoTouch.Foundation.NSIndexPath that is passed as the indexPath argument contains the MonoTouch.Foundation.NSIndexPath.Section and MonoTouch.Foundation.NSIndexPath.Item integers that allow the application developer to locate a specific data item and appropriately assign the cell's relevant visual elements. (Application developers familiar with MonoTouch.UIKit.UITableView will note that MonoTouch.Foundation.NSIndexPath.Item and MonoTouch.Foundation.NSIndexPath.Row are the same value.)
Since these methods, particularly the UICollectionViewDataSource.GetCell method, are called many times during scrolling, the application developer should avoid unnecessary processing during these calls.
C# Example
public class AnimalCell : UICollectionViewCell { private static NSString classId = new NSString ("AnimalCell"); public static NSString ClassId { get { return classId; } } [Export ("initWithFrame:")] public AnimalCell (RectangleF frame) : base (frame) {} //..etc... } public class SimpleCollectionViewController : UICollectionViewController { public override void ViewDidLoad () { Base.ViewDidLoad (); var cv = CollectionView; cv.RegisterClassForCell (typeof(AnimalCell), AnimalCell.ClassId); cv.RegisterClassForSupplementaryView (typeof(HeaderView), UICollectionElementKindSection.Header, HeaderView.ClassId); cv.CollectionViewLayout.RegisterClassForDecorationView (typeof(DecorationView), DecorationView.ClassId); } public override UICollectionViewCell GetCell (UICollectionView collectionView, MonoTouch.Foundation.NSIndexPath indexPath) { var animalCell = (AnimalCell)collectionView.DequeueReusableCell (AnimalCell.ClassId, indexPath); var animal = animals [indexPath.Section * (animals.Count / SectionCount) + indexPath.Item]; animalCell.Image = animal.Image; return animalCell; } public override UICollectionReusableView GetViewForSupplementaryElement (UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath) { var headerView = (HeaderView)collectionView.DequeueReusableSupplementaryView (elementKind, HeaderView.ClassId, indexPath); headerView.Text = "Supplementary View Section " + indexPath.Section.ToString (); return headerView; } //...etc... }
Rather than registering program classes, application developers may choose to register nibs defined with XCode's Interface Builder. The relevant methods are shown in the following table.
Role | Class Registration Method | Nib Registration Method |
---|---|---|
Cell | UICollectionView.RegisterClassForCell | UICollectionView.RegisterNibForCell |
Supplementary View | UICollectionView.RegisterClassForSupplementaryView | UICollectionView.RegisterNibForSupplementaryView |
Decoration View | UICollectionViewLayout.RegisterClassForDecorationView | UICollectionViewLayout.RegisterNibForDecorationView |
To handle events associated with a MonoTouch.UIKit.UICollectionView, the application developer may subtype MonoTouch.UIKit.UICollectionViewDelegate and assign an instance to the UICollectionView.Delegate property.
MonoTouch.UIKit.UICollectionView is a subtype of MonoTouch.UIKit.UIScrollView and MonoTouch.UIKit.UIScrollViewDelegate contains many of the same methods as MonoTouch.UIKit.UIScrollViewDelegate but is not a subtype of that class.
Selecting and highlighting in a MonoTouch.UIKit.UICollectionView follows this sequence:
User Action | UICollectionViewDelegate Methods | UICollectionViewCell Properties |
---|---|---|
Nothing touched | Highlighted == false; Selected == false | |
Finger down in cell | UICollectionViewDelegate.ShouldHighlightItem is called. If it returns false, processing stops. | |
UICollectionViewDelegate.ItemHighlighted is called. | Highlighted == true; Selected == false | |
Finger up | UICollectionViewDelegate.ShouldSelectItem is called. If it returns false, processing stops. | |
UICollectionViewDelegate.ItemSelected is called. UICollectionViewDelegate.ItemUnhighlighted is called. | Highlighted == false; Selected == true |
Deselecting a MonoTouch.UIKit.UICollectionViewCell follows a similar sequence:
User Action | UICollectionViewDelegate Methods | UICollectionViewCell Properties |
---|---|---|
Nothing touched while some MonoTouch.UIKit.UICollectionViewCell is highlighted. | Highlighted == false; Selected == true | |
Finger taps cell (Deselect gesture) | UICollectionViewDelegate.ShouldDeselectItem is called. If it returns false, processing stops. | |
UICollectionViewDelegate.ItemDeselected is called. | Highlighted == false; Selected == false |