Log in to like this post! Create an iOS Flow Layout with Ease Using NucliOS (Obj-C & C#) Torrey Betts / Friday, April 25, 2014 Introduction With the release of NucliOS 2014 Volume 1 we've included a flow layout control (IGFlowLayoutView). This control allows you to easily create a dynamically sized list of items that can be scroll horizontal or vertically, similar to the UICollectionView. Like any other Infragistics control, this powerful flow layout can have its style fully customized, cells reordered or even resized. Creating a Flow Layout The IGFlowLayoutView loads up its data in a similar data source protocol fashion as the IGGridView or Apple's own UITableView. The IGFlowLayoutView requires the implementation of 4 method found in the IGFlowLayoutDataSource protocol. numberOfBlocksInViewport: - the number of blocks both vertical and horizontal that will fit within the flow layout viewport numberOfItemsInFlowLayoutView: - the number of total items to display in the flow layout flowLayoutView:sizeForItemAtIndex: the number of blocks both vertical and horizontal that the specified item will take up flowLayoutView:cellAtIndex: - the IGFlowLayoutViewCell to display in the IGFlowLayoutView One of the many great things about the IGFlowLayoutView is that changes when adding, removing or updating cells can be animated. The code example below demonstrates this by calling an update on each cell to provide a histogram equalizer effect, similar to what you see in audio apps. Objective-C @interface igViewController () <IGFlowLayoutViewDataSource> { IGFlowLayoutView *_flowLayoutView; NSInteger _totalItems; } @end @implementation igViewController - (void)viewDidLoad { [super viewDidLoad]; _totalItems = 10; _flowLayoutView = [[IGFlowLayoutView alloc] initWithFrame:self.view.bounds]; _flowLayoutView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; _flowLayoutView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1.0]; _flowLayoutView.transitionDuration = 0.75; _flowLayoutView.dataSource = self; _flowLayoutView.transform = CGAffineTransformMakeRotation(M_PI); [self.view addSubview:_flowLayoutView]; [_flowLayoutView updateData]; [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; } - (CGSize)numberOfBlocksInViewport:(IGFlowLayoutView *)flowLayoutView { CGSize result = CGSizeMake(_totalItems, 4); return result; } - (NSInteger)numberOfItemsInFlowLayoutView:(IGFlowLayoutView *)flowLayoutView { return _totalItems; } - (CGSize)flowLayoutView:(IGFlowLayoutView *)flowLayoutView sizeForItemAtIndex:(NSInteger)index1 { CGSize result; IGFlowLayoutViewCell *cell = [_flowLayoutView cellAtIndex:index1]; if (!cell) result = CGSizeMake(1, 1); else result = CGSizeMake(1, cell.tag); return result; } - (IGFlowLayoutViewCell *)flowLayoutView:(IGFlowLayoutView *)flowLayoutView cellAtIndex:(NSInteger)index1 { IGFlowLayoutViewCell *cell = [flowLayoutView dequeueReusableCellWithIdentifier:@"CELL"]; if (!cell) { cell = [[IGFlowLayoutViewCell alloc] initWithReuseIdentifier:@"CELL"]; cell.contentInset = UIEdgeInsetsMake(3, 3, 3, 3); cell.tag = 0; UIView *innerView = [[UIView alloc] init]; innerView.layer.backgroundColor = [UIColor colorWithRed:238/255.0f green:197/255.0f blue:91/255.0f alpha:1.0f].CGColor; innerView.layer.cornerRadius = 10.0; innerView.layer.borderWidth = 3.0; innerView.layer.borderColor = [UIColor colorWithWhite:0.3 alpha:0.75].CGColor; cell.contentView = innerView; } return cell; } - (void)timerTick { NSMutableArray *levels = [[NSMutableArray alloc] init]; for (int k = 0; k < _totalItems; k++) { [levels addObject:[NSNumber numberWithInt:arc4random_uniform(4) + 1]]; } for (NSUInteger j = 0; j < _totalItems; j++) { NSInteger levelForColumn = [[levels objectAtIndex:j] intValue]; IGFlowLayoutViewCell *cell = [_flowLayoutView cellAtIndex:j]; cell.tag = levelForColumn; [_flowLayoutView updateItemAtIndex:j]; } } @end C# (Xamarin.iOS) public class FlowLayoutDataSource : IGFlowLayoutViewDataSource { int _totalItems; public FlowLayoutDataSource(int TotalItems) { _totalItems = TotalItems; } public override SizeF NumberOfBlocksInViewport (IGFlowLayoutView flowLayoutView) { SizeF result = new SizeF(_totalItems, 4); return result; } public override int NumberOfItems (IGFlowLayoutView flowLayoutView) { return _totalItems; } public override SizeF SizeForItem (IGFlowLayoutView flowLayoutView, int index) { SizeF result; IGFlowLayoutViewCell cell = flowLayoutView.CellAtIndex (index); if (cell == null) result = new SizeF (1, 1); else result = new SizeF(1, cell.Tag); return result; } public override IGFlowLayoutViewCell CreateCell (IGFlowLayoutView flowLayoutView, int index) { IGFlowLayoutViewCell cell = flowLayoutView.DequeueReusableCell ("CELL") as IGFlowLayoutViewCell; if (cell == null) { cell = new IGFlowLayoutViewCell ("CELL"); cell.ContentInset = new UIEdgeInsets (3, 3, 3, 3); UIView innerView = new UIView (); innerView.Layer.BackgroundColor = UIColor.FromRGBA (238 / 255.0f, 197 / 255.0f, 91 / 255.0f, 1.0f).CGColor; innerView.Layer.CornerRadius = 10.0f; innerView.Layer.BorderWidth = 3.0f; innerView.Layer.BorderColor = UIColor.FromWhiteAlpha (0.3f, 0.75f).CGColor; cell.ContentView = innerView; } return cell; } } public partial class FlowLayoutUpdateItem_CSViewController : UIViewController { IGFlowLayoutView _flowLayoutView; int _totalItems; public FlowLayoutUpdateItem_CSViewController () { } public override void ViewDidLoad () { base.ViewDidLoad (); _totalItems = 10; _flowLayoutView = new IGFlowLayoutView (); _flowLayoutView.Frame = this.View.Bounds; _flowLayoutView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight|UIViewAutoresizing.FlexibleWidth; _flowLayoutView.BackgroundColor = UIColor.FromWhiteAlpha (0.3f, 0.75f); _flowLayoutView.TransitionDuration = 0.75f; _flowLayoutView.DataSource = new FlowLayoutDataSource(_totalItems); _flowLayoutView.Transform = CGAffineTransform.MakeRotation((float)Math.PI); this.View.Add (_flowLayoutView); _flowLayoutView.UpdateData (); NSTimer.CreateRepeatingScheduledTimer (1.0f, () => { Random rnd = new Random(); List<int> levels = new List<int>(); for (int k = 0; k < _totalItems; k++) { levels.Add(rnd.Next(4) + 1); } for (int j = 0; j < _totalItems; j++) { int levelForColumn = levels[j]; IGFlowLayoutViewCell cell = _flowLayoutView.CellAtIndex(j); cell.Tag = levelForColumn; _flowLayoutView.UpdateItemAtIndex(j); } }); } } The final result when the IGFlowLayoutView renders is shown below. Further Reference Below are links to the API reference page as well as the developer's guide, NucliOS forums & NucliOS trial. API Reference for IGFlowLayoutView -http://help.infragistics.com/iOS/2014.1/gridapi/Classes/IGFlowLayoutView.htmlDeveloper's Guide Documentation for IGFlowLayoutView - http://help.infragistics.com/iOS/2014.1/?page=IGFlowLayoutView.htmlNucliOS Forums - http://www.infragistics.com/community/forums/default.aspx?GroupID=92NucliOS Trial - http://www.infragistics.com/products/ios By Torrey Betts