ios 上 self-sizing cell 的過去、現在、與未來

Post on 13-Apr-2017

341 Views

Category:

Engineering

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

iOS self-sizing cell

(Jeff Lin)

• Yahoo AppDevKit - - (Anistar)

• https://github.com/yahoo/AppDevKit

• – iOS BDD - (qcl)

• https://github.com/qcl/zizhi

About me• YAHOO App Engineer

• iOS App

• AppDevKit

Agenda

• Self-sizing

• Self-sizing

• Xcode 8

Self-sizing

/

/

Expandable cell

• iOS dynamic type

• UIFont.preferredFontForTextStyle:

• UIImageView, UILabel, UITextView…

• Container

• UITableView, UICollectionView

• storyboard, xib, constraint

Layout

Self-sizing ?

!• auto self-sizing

• NSString

• sizeWithAttributes

• boundingRectWithSize:options:attributes:context:

• UILabel

• sizeToFit:

• UIScrollView/UITextView

• contentSize

• size ceil()

• sizeToFit: frameconstraint

UITextView contentSize

• sizeForItemAtIndexPath:

• textView.ContentSize

iOS ?

UITableview self sizing

• UILabel numberOfLines = 0

• AutoLayout

self.tableView?.rowHeight = UITableViewAutomaticDimension self.tableView?.estimatedRowHeight = 100

That’s all!

UITableview self sizing

• layout

UICollectionView

• Grid view,

• /layout

UICollectionView self-sizing

AppDevKit• UICollectionViewCell

• subclass ADKTableViewDynamicSizeCell/ADKCollectionViewDynamicSizeCell

• constraint

• collectionView:layout:sizeForItemAtIndexPath:

• ADKNibCacheManager cell

• cell

AppDevKit Solution

AppDevKit Solution

collectionView:layout:sizeForItemAtIndexPath:

1. cell

let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String? let cell = ADKSWNibCacheManager.sharedInstance().instance( className: appName?.appending(".\(SSSmallCardCollectionViewCell.self)")) as! SSSmallCardCollectionViewCell

AppDevKit Solution

2.

let preferSize = CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 100.0) cell.frame = CGRect.init(origin: .zero, size: preferSize)

3. layoutIfNeeded constraint

cell.contentView.layoutIfNeeded()

AppDevKit Solution

4.

func setup(cell: SSSmallCardCollectionViewCell, indexPath: IndexPath) { let productInfo = self.products[indexPath.row] cell.contentView.layoutIfNeeded() cell.titleLabel?.text = productInfo.productTitle ... }

AppDevKit Solution

5.

let size = ADKCellDynamicSizeCalculator.sharedInstance().size(forDynamicHeightCellInstance: cell, preferredSize: preferSize)

return size

Sample Code@objc(collectionView:layout:sizeForItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

// 1. cell let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String? let cell = ADKSWNibCacheManager.sharedInstance().instance(className: appName?.appending(".\(SSSmallCardCollectionViewCell.self)")) as! SSSmallCardCollectionViewCell

// 2. let preferSize = CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 100.0) cell.frame = CGRect.init(origin: .zero, size: preferSize)

// 3. layoutIfNeeded constraint cell.contentView.layoutIfNeeded()

// 4. setup(cell: cell, indexPath: indexPath)

// 5. let size = ADKCellDynamicSizeCalculator.sharedInstance().size(forDynamicHeightCellInstance: cell, preferredSize: CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 0.0)) return size }

Recap1. cell

2.

3. layoutIfNeededconstraint

4.

5.

ImageView

Title

Description

Price

Recap1. cell

2.

3. layoutIfNeededconstraint

4.

5.

ImageView

Title

Description

Price

Recap1. cell

2.

3. layoutIfNeededconstraint

4.

5.

ImageView

Title

Description

Price

Recap1. cell

2.

3. layoutIfNeededconstraint

4.

5.

ImageView

Title

Description

Price

ImageView

SO NICE

$ 790

ImageView

SO NICE

790

Recap1. cell

2.

3. layoutIfNeededconstraint

4.

5.

ImageView

SO NICE

$ 790

SO NICE

,

,

$ 790

AppDevKit Solution

ADKCellDynamicSizeCalculator.sharedInstance().size(forDynamicHeightCellInstance: cell, preferredSize: CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 0.0))

10px

How AppDevKit works?•CGSize resultSize = [contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; resultSize.width = preferredSize.width; resultSize.height = MAX(resultSize.height, preferredSize.height);

systemLayoutSizeFittingSize

• UILayoutFittingCompressedSize

• view constraints size

• UILayoutFittingExpandedSize

• view constraints size

layoutIfNeeds

• layoutIfNeeds

• reloadData contentSize

• Animate autoLayout

contentSize

// contentSize: {0, 0}collectionView.dataSource = self.delegator// contentSize: {0, 0}collectionView.reloadData()// contentSize: {0, 0}collectionView.layoutIfNeeded// contentSize: {375, 2557.5}

layoutIfNeeds-Animation

viewForAnimate.someConstraint.constanst = 0.0 UIView.animate(withDuration: 0.3) {

viewForAnimate.layoutIfNeeded() }

UIView.animate(withDuration: 0.3) { viewForAnimate.frame = CGRect.init(origin: .zero, size: CGSize.init(width: 100, height: 100))

}

Frame base layout

Constraint Autolayout

iOS ?

cell

• collectionView:layout:sizeForItemAtIndexPath:

• Customized UICollectionViewLayout

estimatedItemSize

estimatedItemSize• iOS 8 above

• UICollectionViewFlowLayout

• estimatedItemSize

• UICollectionViewCell

• preferredLayoutAttributesFittingAttributes

estimatedItemSize

• UITableView estimatedRowHeight

• UICollectionViewFlowLayoutflowLayout.estimatedItemSize = CGSize.init(width: UIScreen.main.bounds.size.width / 2 - 20, height: 100)

Sample Codefunc preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { self.contentView.layoutIfNeeded() layoutAttributes.frame.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height layoutAttributes.frame.size.width = self.bounds.size.width

return layoutAttributes }

• class reference super.preferredLayoutAttributesFitting(layoutAttributes)

• newLayoutAttributes size 1000x1000

• iOS 10self.contentView.layoutIfNeeded()

• estimatedItemSize cellpreferredLayoutAttributesFitting

• estimatedItemSize sizeForItemAtIndexPath

preferredLayoutAttributesFittingAttributes

preferredLayoutAttributesFittingAttributes

• + ...

•constraint

• willDisplayCell

• ADKSetConstraintConstant:forAttribute: can help!

• cellestimatedItemSize

flowLayout

•collectionView:layout:sizeForItemAtIndexPath:

Expandable cell

• estimatedItemSize+invalidLayout+UIViewAnimation

• sizeForCellAtIndexPath+performBatchUpdate:

• TableView

• estimatedRowHeight

• CollectionView

• cell estimatedItemSize

• sizeForItemAtIndexPath

• Custom flowLayout

• AppDevKit might help for nib!

Xcode 8 & iOS 10

self-sizing in iOS 10

• WWDC 216 What's New in UICollectionView in iOS 10

flowLayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize

xib in Xcode 8

xib in Xcode 8

• xib constraint frame

• init frame

• Update:Xcode 8.1

Frame size1000!

xib in Xcode 8

NSLayoutConstraint(item: star, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: self.frame.height).isActive = true;

” ”

1000x1000 star!

Solution

• or 0NSLayoutConstraint(item: star, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1.0, constant: 0.0).isActive = true;

xibXcode 7

Xcode 8

constraint...

• auto layout constraint

• contentView

layoutIfNeeded

• preferredMaxLayoutWidth

• xib

• size constraint

• constraint self.frame.size

constraint ...

Self-sizing checklist

• estimatedItemSize

• cellpreferredLayoutAttributesFittingAttributes

• self-sizing constraint

Self-sizing checklist• sizeForItemAtIndexPath:

• cache cell

• constraint frame

• self-sizing constraint

• ADKNibSizeCalculator & ADKCellDynamicSizeCalculator can help!

• self-sizing constraint

• ( )

• preferredMaxLayoutWidth

Thank you!

top related