你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS7技巧 >> Swift多列表格組件的基本功能的例子

Swift多列表格組件的基本功能的例子

編輯:IOS7技巧
下文我們一起來看一篇關於Swift多列表格組件的基本功能的例子,希望這篇教程能夠幫助到各位同學,有興趣的朋友可以進來看看哦,具體如下文所示。 與桌面、Web應用不同,受限於屏幕尺寸,移動APP常常采用單列表格來顯示列表數據。但有時我們需要使用多列表格來展示數據(比如:報表數據顯示,或iPad這種大屏設備上展示多欄數據),這些通過網格(UICollectionView)的自定義布局功能就可以實現。   1,多列表格(multi-column table control)效果圖 原文:Swift - 多列表格組件的實現(樣例1:基本功能的實現) 2,功能說明: (1)表格列頭的標題文字加粗,內容區域的文字正常 (2)表格邊框為1像素黑色邊框 (3)第一列文字居左,其余列文字居中顯示(居左的文字離左側還是有5個像素距離) (4)每列單元格寬度不是平均分配的。而是從右往左,根據表頭文字計算當前列的寬度。剩下的空間就都分配給第一列。 (5)整個組件內部設置了 contentInset,給左右兩側各設置了10像素的距離。這樣組件外部設置100%寬時,左右邊框也不會頂到屏幕邊緣。同時如果有滾動條的時候,滾動條也不會蓋在表格內容區域上方。 (6)點擊單元格控制台會打印出對應的坐標位置。 原文:Swift - 多列表格組件的實現(樣例1:基本功能的實現)   3,關於collection view重新計算布局時機 (1)shouldInvalidateLayoutForBoundsChange() 方法返回 true,表示當 collection view 的 bounds 改變時,就要重新計算布局。
(2)除了collection view 改變尺寸大小時 bounds 會改變, scroll view 的 bounds 在滾動時也會改變。
(3)本例中,collection view 在滾動的情況下沒必要計算更新布局,否則拖動滾動條的時候布局會不斷地丟棄重新計算,影響性能。  (4)這裡在 shouldInvalidateLayoutForBoundsChange() 中做判斷,只有 collection view 寬度變化時才返回true重新計算布局,否則返回false。   4,項目代碼 --- UICollectionGridViewController.swift(組件類) ---


import Foundation
import UIKit
 
//多列表格組件(通過CollectionView實現)
class UICollectionGridViewController: UICollectionViewController {
    //表頭數據
    var cols: [String]! = []
    //行數據
    var rows: [[AnyObject]]! = []
    //單元格內容居左時的左側內邊距
    private var cellPaddingLeft:CGFloat = 5
     
    init() {
        //初始化表格布局
        let layout = UICollectionGridViewLayout()
        super.init(collectionViewLayout: layout)
        layout.viewController = self      
        collectionView!.backgroundColor = UIColor.whiteColor()
        collectionView!.registerClass(UICollectionViewCell.self,
            forCellWithReuseIdentifier: "cell")
        collectionView!.delegate = self
        collectionView!.dataSource = self
        collectionView!.directionalLockEnabled = true
        collectionView!.contentInset = UIEdgeInsetsMake(0, 10, 0, 10)
        collectionView!.bounces = false
    }
     
    required init?(coder aDecoder: NSCoder) {
        fatalError("UICollectionGridViewController.init(coder:) has not been implemented")
    }
     
    //設置列頭數據
    func setColumns(columns: [String]) {
        cols = columns
    }
     
    //添加行數據
    func addRow(row: [AnyObject]) {
        rows.append(row)
        collectionView!.collectionViewLayout.invalidateLayout()
        collectionView!.reloadData()
    }
     
    override func viewDidLoad() {
        super.viewDidLoad()
    }
     
    override func viewDidLayoutSubviews() {
        collectionView!.frame = CGRectMake(0, 0, view.frame.width, view.frame.height)
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
     
    //返回表格總行數
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView)
        -> Int {
        if cols.isEmpty {
            return 0
        }
        //總行數是:記錄數+1個表頭
        return rows.count + 1
    }
     
    //返回表格的列數
    override func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int {
            return cols.count
    }
     
    //單元格內容創建
    override func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
             
            let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell",
                forIndexPath: indexPath) as UICollectionViewCell           
            //單元格邊框
            cell.layer.borderWidth = 1
            cell.backgroundColor = UIColor.whiteColor()
            cell.clipsToBounds = true
             
            //先清空內部原有的元素
            for subview in cell.subviews {
                subview.removeFromSuperview()
            }
             
            //添加內容標簽
            let label = UILabel(frame: CGRectMake(0, 0, cell.frame.width,
                cell.frame.height))
             
            //第一列的內容左對齊,其它列內容居中
            if indexPath.row != 0 {
                label.textAlignment = NSTextAlignment.Center
            }else {
                label.textAlignment = NSTextAlignment.Left
                label.frame.origin.x = cellPaddingLeft
            }
             
            //設置列頭單元格,內容單元格的數據
            if indexPath.section == 0 {
                let text = NSAttributedString(string: cols[indexPath.row], attributes: [
                    NSFontAttributeName:UIFont.boldSystemFontOfSize(15)
                    ])
                label.attributedText = text
            } else {
                label.font = UIFont.systemFontOfSize(15)
                label.text = "\(rows[indexPath.section-1][indexPath.row])"
            }
            cell.addSubview(label)
             
            return cell
    }
     
    //單元格選中事件
    override func collectionView(collectionView: UICollectionView,
        didSelectItemAtIndexPath indexPath: NSIndexPath) {
            //打印出點擊單元格的[行,列]坐標
            print("點擊單元格的[行,列]坐標: [\(indexPath.section),\(indexPath.row)]")
    }
}

--- UICollectionGridViewLayout.swift(布局類) ---
import Foundation
import UIKit
 
//多列表格組件布局類
class UICollectionGridViewLayout: UICollectionViewLayout {
    //記錄每個單元格的布局屬性
    private var itemAttributes: [[UICollectionViewLayoutAttributes]] = []
    private var itemsSize: [NSValue] = []
    private var contentSize: CGSize = CGSizeZero
    //表格組件視圖控制器
    var viewController: UICollectionGridViewController!
     
    //准備所有view的layoutAttribute信息
    override func prepareLayout() {
        if collectionView!.numberOfSections() == 0 {
            return
        }
         
        var column = 0
        var xOffset: CGFloat = 0
        var yOffset: CGFloat = 0
        var contentWidth: CGFloat = 0
        var contentHeight: CGFloat = 0
         
        if itemAttributes.count > 0 {
            return
        }
         
        itemAttributes = []
        itemsSize = []
         
        if itemsSize.count != viewController.cols.count {
            calculateItemsSize()
        }
         
        for var section = 0; section < collectionView?.numberOfSections(); section++ {
            var sectionAttributes: [UICollectionViewLayoutAttributes] = []
            for var index = 0; index < viewController.cols.count; index++ {
                let itemSize = itemsSize[index].CGSizeValue()
                 
                let indexPath = NSIndexPath(forItem: index, inSection: section)
                let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath:
                    indexPath)
                //除第一列,其它列位置都左移一個像素,防止左右單元格間顯示兩條邊框線
                if index == 0{
                    attributes.frame = CGRectIntegral(CGRectMake(xOffset, yOffset,
                        itemSize.width, itemSize.height))
                }else {
                    attributes.frame = CGRectIntegral(CGRectMake(xOffset-1, yOffset,
                        itemSize.width+1, itemSize.height))
                }
                 
                sectionAttributes.append(attributes)
                 
                xOffset = xOffset+itemSize.width
                column++
                 
                if column == viewController.cols.count {
                    if xOffset > contentWidth {
                        contentWidth = xOffset
                    }
                     
                    column = 0
                    xOffset = 0
                    yOffset += itemSize.height
                }
            }
            itemAttributes.append(sectionAttributes)
        }
         
        let attributes = itemAttributes.last!.last! as UICollectionViewLayoutAttributes
        contentHeight = attributes.frame.origin.y + attributes.frame.size.height
        contentSize = CGSizeMake(contentWidth, contentHeight)
    }
     
    //需要更新layout時調用
    override func invalidateLayout() {
        itemAttributes = []
        itemsSize = []
        contentSize = CGSizeZero
        super.invalidateLayout()
    }
     
    // 返回內容區域總大小,不是可見區域
    override func collectionViewContentSize() -> CGSize {
        return contentSize
    }
     
    // 這個方法返回每個單元格的位置和大小
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath)
        -> UICollectionViewLayoutAttributes? {
            return itemAttributes[indexPath.section][indexPath.row]
    }
     
    // 返回所有單元格位置屬性
    override func layoutAttributesForElementsInRect(rect: CGRect)
        -> [UICollectionViewLayoutAttributes]? {
            var attributes: [UICollectionViewLayoutAttributes] = []
            for section in itemAttributes {
                attributes.appendContentsOf(section.filter(
                    {(includeElement: UICollectionViewLayoutAttributes) -> Bool in
                        return CGRectIntersectsRect(rect, includeElement.frame)
                }))
            }
            return attributes
    }
     
    //當邊界發生改變時,是否應該刷新布局。
    //本例在寬度變化時,將重新計算需要的布局信息。
    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        let oldBounds = self.collectionView?.bounds
        if CGRectGetWidth(oldBounds!) != CGRectGetWidth(newBounds) {
            return true
        }else {
            return false
        }
    }
     
    //計算所有單元格的尺寸(每一列各一個單元格)
    func calculateItemsSize() {
        var remainingWidth = collectionView!.frame.width -
            collectionView!.contentInset.left - collectionView!.contentInset.right
         
        for var index = viewController.cols.count-1; index >= 0; index-- {
            let newItemSize = sizeForItemWithColumnIndex(index,
                remainingWidth: remainingWidth)
            remainingWidth -= newItemSize.width
            let newItemSizeValue = NSValue(CGSize: newItemSize)
            //由於遍歷列的時候是從尾部開始遍歷了,因此將結果插入數組的時候都是放人第一個位置
            itemsSize.insert(newItemSizeValue, atIndex: 0)
        }
    }
     
    //計算某一列的單元格尺寸
    func sizeForItemWithColumnIndex(columnIndex: Int, remainingWidth: CGFloat) -> CGSize {
        let columnString = viewController.cols[columnIndex]
        //根據列頭標題文件,估算各列的寬度
        let size = NSString(string: columnString).sizeWithAttributes([
            NSFontAttributeName:UIFont.systemFontOfSize(15),
            NSUnderlineStyleAttributeName:NSUnderlineStyle.StyleSingle.rawValue
            ])
         
        //如果有剩余的空間則都給第一列
        if columnIndex == 0 {
            return CGSizeMake(max(remainingWidth, size.width + 17), size.height + 10)
        }
        //行高增加10像素,列寬增加17像素
        return CGSizeMake(size.width + 17, size.height + 10)
    }
}

--- ViewController.swift(測試類) ---

import UIKit
 
class ViewController: UIViewController {
     
    var gridViewController: UICollectionGridViewController!
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        gridViewController = UICollectionGridViewController()
        gridViewController.setColumns(["客戶", "消費金額", "消費次數", "滿意度"])
        gridViewController.addRow(["hangge", "100", "8", "60%"])
        gridViewController.addRow(["張三", "223", "16", "81%"])
        gridViewController.addRow(["李四", "143", "25", "93%"])
        gridViewController.addRow(["王五", "75", "2", "53%"])
        gridViewController.addRow(["韓梅梅", "43", "12", "33%"])
        gridViewController.addRow(["李雷", "33", "27", "45%"])
        gridViewController.addRow(["王大力", "33", "22", "15%"])
        view.addSubview(gridViewController.view)
    }
     
    override func viewDidLayoutSubviews() {
        gridViewController.view.frame = CGRectMake(0, 50, view.frame.width,
            view.frame.height-60)
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }   
}

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved