IOS implementation Custom Layout waterfall Flow _ios

Source: Internet
Author: User
Tags abs

Waterfall flow is one of the ways in which electrical business applications display goods, such as illustrations

Waterfall flows are implemented in the following ways, usually

    • Implemented via UITableView (not commonly used)
    • Implemented through Uiscrollview (larger workload)
    • Implemented through Uicollectionview (usually in the manner used)

First, Uicollectionview Foundation
1, Uicollectionview and UITableView have a lot of similar places, such as

    • Provide data through the data source
    • Performs related events through the agent
    • You can customize the cell and involve cell reuse.
    • are inherited from Uiscrollview, with scrolling effects

2, the characteristics of Uicollectionview

    • You need to have a uicollectionviewlayout class (usually the Uicollectionviewflowlayout class) or its subclass object to determine the layout of the cell
    • You can implement uicollectionviewlayout subclasses to customize the scrolling direction of Uicollectionview and the layout of the cell

3, Uicollectionviewlayout of the subclass Uicollectionviewflowlayout

    • Uicollectionviewflowlayout is the flow layout
    • One of the most commonly used layout methods for flow layout Uicollectionview

Two, custom layout
1, custom layout needs to implement Uicollectionviewlayout subclass
2, custom layout common methods
Initialize Layout

-(void) preparelayout
{
  //typically completes a layout initialization operation in this method
}

Whether to update the layout when the dimension changes

-(BOOL) Shouldinvalidatelayoutforboundschange: (cgrect) newbounds
{
  //default return Yes
}

Elements of Layout Uicollectionview

-(Nullable nsarray<__kindof uicollectionviewlayoutattributes *> *) Layoutattributesforelementsinrect: (CGRect) Rect
{
  //This method needs to return an array of all the element layout properties in the Rect area
}
-(Nullable uicollectionviewlayoutattributes *) Layoutattributesforitematindexpath: (Nsindexpath *) Indexpath
{
  //This method returns the layout properties of the element at Indexpath position
}

Modify Uicollectionview Stop scrolling offset

-(Cgpoint) Targetcontentoffsetforproposedcontentoffset: (cgpoint) Proposedcontentoffset withScrollingVelocity: ( Cgpoint) Velocity
{
  //return value is, Uicollectionview final stop point
}

Third, the example
1, realize the effect

2, the realization of ideas

    • Implemented by Uicollectionview
    • Custom layout, i.e. horizontal flow layout and circular general layout
    • By Uicollectionview's proxy method, when you click on the cell, delete it
    • Change the layout when you point to the view of the controller by listening to the UIView touch events

3. Implementation steps
self-defined transverse flow layout
Initialize Layout

-(void) preparelayout
{
  [super preparelayout];
  Set scrolling direction
  self.scrolldirection = uicollectionviewscrolldirectionhorizontal;
  Set the inner margin
  cgfloat inset = (self.collectionview.frame.size.width-self.itemsize.width) * 0.5;
  Self.sectioninset = Uiedgeinsetsmake (0, inset, 0, inset);
}

Specifies that when a dimension changes, the layout is updated

-(BOOL) Shouldinvalidatelayoutforboundschange: (cgrect) newbounds
{return
  YES;
}

Set layout properties for all elements

-(Nullable nsarray<uicollectionviewlayoutattributes *> *) Layoutattributesforelementsinrect: (CGRect) rect
{
  //Get the layout properties of all elements in the Rect area
  nsarray *array = [Super Layoutattributesforelementsinrect:rect];

  Gets the midpoint of the Uicollectionview, taking the upper-left corner of the Contentview as the origin
  cgfloat CenterX = self.collectionview.contentoffset.x + Self.collectionView.frame.size.width * 0.5;

  Resets the layout properties of all elements in the Rect area, that is, based on their intensity from the midpoint of the Uicollectionview, to change their size for
  (Uicollectionviewlayoutattributes *attribute in Array)
  {
    //get distance from midpoint
    cgfloat delta = ABS (Attribute.center.x-centerx);
    Compute the scaling ratio
    cgfloat scale = 1-delta/self.collectionview.bounds.size.width;
    Set layout properties
    Attribute.transform = Cgaffinetransformmakescale (scale, scale);
  }

  Returns the layout properties for all elements return
  [array copy];
}

Sets the offset of the Uicollectionview stop scroll to the center point

-(Cgpoint) Targetcontentoffsetforproposedcontentoffset: (cgpoint) Proposedcontentoffset withScrollingVelocity: ( Cgpoint) Velocity
{
  //Compute the final displayed rectangular frame
  cgrect rect;
  rect.origin.x = proposedcontentoffset.x;
  RECT.ORIGIN.Y = 0;
  Rect.size = self.collectionView.frame.size;

  Gets the layout properties of the element that is ultimately displayed in the rectangle box
  nsarray *array = [Super Layoutattributesforelementsinrect:rect];

  Gets the midpoint of the Uicollectionview, taking the upper-left corner of the Contentview as the origin
  cgfloat CenterX = proposedcontentoffset.x + Self.collectionView.frame.size.width * 0.5;

  Gets the shortest distance of all elements to the midpoint
  cgfloat mindelta = maxfloat;
  For (uicollectionviewlayoutattributes *attribute in array)
  {
    CGFloat delta = attribute.center.x-centerx;< C16/>if (ABS (Mindelta) > abs (Delta))
    {
      mindelta = Delta;
    }
  }

  Change the uicollectionview of the offset
  proposedcontentoffset.x + = Mindelta;
  return proposedcontentoffset;
}

Custom Round general Layout
Define member properties, save all layout properties

@property (nonatomic, strong) Nsmutablearray *attrsarray;

Lazy load, initialize Attrsarray

-(Nsmutablearray *) Attrsarray
{
  if (_attrsarray = = nil)
  {
    _attrsarray = [Nsmutablearray array];
  } return
  _attrsarray;
}

Initialize layout

-(void) preparelayout
{
  [super preparelayout];

  Remove all old layout Properties
  [Self.attrsarray removeallobjects];

  Gets the number of elements
  nsinteger count = [Self.collectionview numberofitemsinsection:0];
  Layout all elements for
  (Nsinteger i = 0; i<count; i++)
  {
    Nsindexpath *indexpath = [Nsindexpath indexpathforitem : I insection:0];
    Sets and gets the layout properties of the Indexpath location element
    uicollectionviewlayoutattributes *attrs = [Self Layoutattributesforitematindexpath: Indexpath];
    Adds the layout property of the Indexpath location element to all layout property Arrays
    [Self.attrsarray addobject:attrs];
  }


Elements of the layout Indexpath position

-(Nullable Uicollectionviewlayoutattributes *) Layoutattributesforitematindexpath: (nonnull nsindexpath *) IndexPath
{
  //Get the number of elements
  nsinteger count = [Self.collectionview numberofitemsinsection:0];

  /** Set the center layout//
  /Set the radius of the circle
  cgfloat radius =;
  The position of the center
  cgfloat OX = self.collectionView.frame.size.width * 0.5;
  CGFloat OY = self.collectionView.frame.size.height * 0.5;
  Gets the layout properties of the element for the Indexpath position
  uicollectionviewlayoutattributes *attrs = [uicollectionviewlayoutattributes Layoutattributesforcellwithindexpath:indexpath];
  Set dimension
  attrs.size = Cgsizemake (m);
  Set position
  if (count = = 1)
  {
    attrs.center = Cgpointmake (OX, OY);
  }
  else
  {
    CGFloat angle = (2 * m_pi/count) * INDEXPATH.ITEM;
    CGFloat CenterX = oX + radius * sin (angle);
    CGFloat CenterY = oY + radius * cos (angle);
    Attrs.center = Cgpointmake (CenterX, centery);
  }
  Returns the Layout property of the Indexpath position element return
  attrs.
}

Layout all elements within a specified area

-(Nullable nsarray<uicollectionviewlayoutattributes *> *) Layoutattributesforelementsinrect: (CGRect) rect
{
  //returns the layout properties of all elements return
  Self.attrsarray;
}

Custom CE ll via Xib
set member properties to save pictures inside the cell

/** Picture Name * *

@property (nonatomic, copy) NSString *imagename;

Initializing cell

-(void) awakefromnib
{
  //Layer set border
  self.imageView.layer.borderColor = [Uicolor Whitecolor]. Cgcolor;
  Self.imageView.layer.borderWidth = 6;
  Self.imageView.layer.cornerRadius = 3;
}

To set the Image property of ImageView within a cell

-(void) Setimagename: (NSString *) imagename
{
  _imagename = [imagename copy];
  Self.imageView.image = [UIImage imagenamed:imagename];
}

Load Picture Resource
Save all picture names through member properties

/** All Pictures * * *
@property (nonatomic, strong) Nsmutablearray *imagenames;

Lazy load, initialize picture array group

-(Nsmutablearray *) imagenames
{
  if (_imagenames = = nil)
  {
    Nsmutablearray *imagenames = [ Nsmutablearray array];
    for (Nsinteger i = 0; i<20; i++)
    {
      NSString *imagename = [NSString stringwithformat:@ "%zd", i + 1];
      [Imagenames addobject:imagename];
    }
    _imagenames = imagenames;
  }
  return _imagenames;
}

Create Uicollectionview
Save the Uicollectionview object through member properties to change the layout

@property (nonatomic, weak) Uicollectionview *collectionview;

Create and set CollectionView

-(void) Setupcollectionview
{
  //Set frame
  cgfloat collectionvieww = self.view.bounds.size.width;
  CGFloat COLLECTIONVIEWH =;
  CGRect frame = CGRectMake (0, COLLECTIONVIEWW, COLLECTIONVIEWH);

  Create layout
  Lypcirclelayout *layout = [[Lypcirclelayout alloc] init];

  Create CollectionView
  Uicollectionview *collectionview = [[Uicollectionview alloc] Initwithframe:frame Collectionviewlayout:layout];
  Self.collectionview = CollectionView;

  Sets the CollectionView data source and proxy
  collectionview.datasource = self;
  Collectionview.delegate = self;

  Add CollectionView to the controller's view
  [Self.view Addsubview:collectionview];
}

The method of realizing Uicollectionview data source
Register Cell

/** set reuse means
/static nsstring *const ID = @ "Photo";
-(void) viewdidload
{
  [super viewdidload];

  [Self setupcollectionview];

  Registered cell
  [Self.collectionview registernib:[uinib nibwithnibname:nsstringfromclass ([Lypphotocell class]) bundle : nil] forcellwithreuseidentifier:id];
}

Set the number of elements

-(Nsinteger) CollectionView: (nonnull uicollectionview *) CollectionView numberofitemsinsection: (NSInteger) Section
{return
  self.imageNames.count;
}

Set properties for each element

-(Uicollectionviewcell *) CollectionView: (nonnull uicollectionview *) CollectionView Cellforitematindexpath: (nonnull Nsindexpath *) Indexpath
{
  //Remove cell from cache pool according to reuse indication, if not in cache pool, automatically create
  lypphotocell *cell = [CollectionView Dequeuereusablecellwithreuseidentifier:id Forindexpath:indexpath];
  Set the ImageName property of the cell
  cell.imagename = Self.imagenames[indexpath.item];

  Returns the cell return
  cell;


Implement Uicollectionview proxy method, realize click an element to delete its function

-(void) CollectionView: (nonnull uicollectionview *) CollectionView Didselectitematindexpath: (nonnull NSIndexPath *) Indexpath
{
  //Remove the picture name from the array
  [Self.imagenames RemoveObjectAtIndex:indexPath.item];
  Deletes the element of the Indexpath position in the CollectionView
  [Self.collectionview Deleteitemsatindexpaths:@[indexpath]];

Click on the Monitor controller view, replace the layout

-(void) Touchesbegan: (nonnull nsset<uitouch *> *) touches withevent: (Nullable uievent *) event
{
  // Determine the type of current layout
  if ([Self.collectionView.collectionViewLayout Iskindofclass:[lyplinelayout class]])
  {
    // Flow layout, switch to circular layout
    [Self.collectionview setcollectionviewlayout:[[lypcirclelayout alloc] init] animated:yes];
  } else
  {
    //circular layout, switch to flow layout
    lyplinelayout *layout = [[Lyplinelayout alloc] init];
    Set the dimensions of the element, and if not set, use the automatic calculation dimension
    layout.itemsize = Cgsizemake (130, 130);
    [Self.collectionview setcollectionviewlayout:layout animated:yes]; 
  }


The above is the entire content of this article, I hope to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.