美文网首页UI效果iOS,object-c和swift开发swift学习笔记
CollectionView 居左对齐(搜索、历史记录)

CollectionView 居左对齐(搜索、历史记录)

作者: 滚滚猫 | 来源:发表于2016-09-12 13:33 被阅读410次

    之前做使用collection做历史记录,不管sollection的怎么设置,item之间能设置最小距离,却不能设置最大距离,所以总是达不到预期效果。后来查看资料重写UICollectionViewFlowLayout方法来达到预期效果。废话不多说,上代码。

    未完成效果.png 预期效果.png

    一、下面是继承UICollectionViewFlowLayout写的类

    import UIKit
    
    extension UICollectionViewLayoutAttributes {
    
        /** 每行第一个item左对齐 **/
        func leftAlignFrame(sectionInset:UIEdgeInsets) {
            var frame = self.frame
            frame.origin.x = sectionInset.left
            self.frame = frame
        }
    }
    
    class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
    
        //MARK: - 重新UICollectionViewFlowLayout的方法
    
        /** Collection所有的UICollectionViewLayoutAttributes */
        override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            let attributesToReturn = super.layoutAttributesForElementsInRect(rect)!
            for attributes in attributesToReturn {
                if nil == attributes.representedElementKind {
                    let indexPath = attributes.indexPath
                    attributes.frame = self.layoutAttributesForItemAtIndexPath(indexPath)!.frame
                }
            }
            return attributesToReturn
        }
    
        /** 每个item的UICollectionViewLayoutAttributes */
        override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
            //现在item的UICollectionViewLayoutAttributes
            let currentItemAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)!
            //现在section的sectionInset
            let sectionInset = self.evaluatedSectionInset(indexPath.section)
            //是否是section的第一个item
            let isFirstItemInSection = indexPath.item == 0
            //出去section偏移量的宽度
            let layoutWidth: CGFloat = CGRectGetWidth(self.collectionView!.frame) - sectionInset.left - sectionInset.right
            //是section的第一个item
            if isFirstItemInSection {
                //每行第一个item左对齐
                currentItemAttributes.leftAlignFrame(sectionInset)
                return currentItemAttributes
            }
        
            //前一个item的NSIndexPath
            let previousIndexPath = NSIndexPath(forItem: indexPath.item - 1, inSection: indexPath.section)
            //前一个item的frame
            let previousFrame = self.layoutAttributesForItemAtIndexPath(previousIndexPath)!.frame
            //为现在item计算新的left
            let previousFrameRightPoint: CGFloat = previousFrame.origin.x + previousFrame.size.width
            //现在item的frame
            let currentFrame = currentItemAttributes.frame
            //现在item所在一行的frame
            let strecthedCurrentFrame = CGRectMake(sectionInset.left, currentFrame.origin.y, layoutWidth, currentFrame.size.height)
        
            //previousFrame和strecthedCurrentFrame是否有交集,没有,说明这个item和前一个item在同一行,item是这行的第一个item
            let isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)
            //item是这行的第一个item
            if isFirstItemInRow {
                //每行第一个item左对齐
                currentItemAttributes.leftAlignFrame(sectionInset)
                return currentItemAttributes
            }
            //不是每行的第一个item
            var frame = currentItemAttributes.frame
            //为item计算新的left = previousFrameRightPoint + item之间的间距
            frame.origin.x = previousFrameRightPoint + self.evaluatedMinimumInteritemSpacing(indexPath.item)
            //为item的frame赋新值
            currentItemAttributes.frame = frame
            return currentItemAttributes
        }
    
        //MARK: - System
    
        /** item行间距 **/
        private func evaluatedMinimumInteritemSpacing(ItemAtIndex:Int) -> CGFloat     {
            if let delete = self.collectionView?.delegate {
                weak var delegate = (delete as! UICollectionViewDelegateFlowLayout)
                if delegate!.respondsToSelector(#selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:minimumInteritemSpacingForSectionAtIndex:))) {
                    let mini =  delegate?.collectionView!(self.collectionView!, layout: self, minimumInteritemSpacingForSectionAtIndex: ItemAtIndex)
                    if mini != nil {
                        return mini!
                    }
                }
            }
            return self.minimumInteritemSpacing
        }
    
        /** section的偏移量 **/
        private func evaluatedSectionInset(itemAtIndex:Int) -> UIEdgeInsets {
            if let delete = self.collectionView?.delegate {
                weak var delegate = (delete as! UICollectionViewDelegateFlowLayout)
                if delegate!.respondsToSelector(#selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:insetForSectionAtIndex:))) {
                    let sectionInset =  delegate?.collectionView!(self.collectionView!, layout: self, insetForSectionAtIndex: itemAtIndex)
                    if sectionInset != nil {
                        return sectionInset!
                    }
                }
            }
            return self.sectionInset
        }
    }
    

    二、�下面在collectionView中使用这个类,我的collectionView是使用xib创建的。

    /// 搜索记录
    @IBOutlet weak var collectionView: UICollectionView!
    /// 历史搜索类型
    var historyArray = [String]()
    
    override func awakeFromNib() {
        super.awakeFromNib()
    
        historyArray = ["关键词","iOS学习基础","牛奶","跳绳","轮滑鞋","香蕉","面包","苹果梨","苹果"]
    
        let layout = UICollectionViewLeftAlignedLayout()
        //竖向cell之间的距离
        layout.minimumLineSpacing = 15
        //横向cell之间的距离,没有设置0.0
        layout.minimumInteritemSpacing = 10
        //section的header的大小
        layout.headerReferenceSize = CGSizeMake(ScreenWidth , 44);
        //section的偏移量
        layout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10)
        //collectionView的偏移量
        collectionView.contentInset = UIEdgeInsetsMake(0, 0, 5, 0)
        //SearchCell:xib中item的identifier
        collectionView.registerNib(UINib.init(nibName: "SearchCell", bundle: nil), forCellWithReuseIdentifier: "SearchCell")
        //SearchHeaderView中sender的header的identifier
        collectionView.registerNib(UINib.init(nibName: "SearchHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "SearchHeaderView")
        collectionView.collectionViewLayout = layout
    }
    
    //MARK: - UICollectionViewDataSource
    
    /** Section数 */
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int{
        if historyArray.count > 0 {
            return 1
        }
        return 0
    }
    
    /** Items数 */
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return historyArray.count
    }
    
    /** Items创建 */
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("SearchCell", forIndexPath: indexPath) as? SearchCell
        cell?.name.text = historyArray[indexPath.item]
        return cell!
    }
    
    /** collection的header创建 */
    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        let view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "SearchHeaderView", forIndexPath: indexPath) as? SearchHeaderView
        return view!
    }
    
    //MARK: - UICollectionViewDelegate
    
    /** 历史记录关键词点击 */
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
       
    }
    
    //MARK: - UICollectionViewDelegateFlowLayout
    
    /** 设置关键词大小 */
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        let name = historyArray[indexPath.item]
        let size = self.boundingRectWithSize(CGSizeMake(ScreenWidth - 20, 30), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(12)], context: nil).size
        let with = size.width
        return CGSizeMake(with + 40, 30)
    }
    

    参考文档
    http://code.cocoachina.com/view/126206

    end:小编是很认真的写文哦,如果小编的文对您有用,一定要点“喜欢”哦!如果有问题欢迎评论

    相关文章

      网友评论

        本文标题:CollectionView 居左对齐(搜索、历史记录)

        本文链接:https://www.haomeiwen.com/subject/xcjpettx.html