手把手教你使用Layout寫瀑布流

思路:
0.明確自定義布局的核心方法:layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes],他是用來(lái)顯示cell的布局的惧浴,所有的cell妹田,但是那稽屏,這個(gè)方法可能多次調(diào)用欠动,所以镐躲,創(chuàng)建的時(shí)候要在prepare方法中寫骆捧,但是权均,返回attribute有專門的方法顿膨,計(jì)算設(shè)置attire的各種屬性--方法是layoutAttributesForItemAtIndexPath,我們需要啥屬性,滴啊用他叽赊,然后在prepare獲取每一個(gè)屬性就好

1.繼承自UICollectionViewLayout創(chuàng)建一個(gè)新的布局對(duì)象WFWaterFlowLayout
2.寫出數(shù)據(jù)源方法恋沃,給定colletionView這個(gè)布局
3.重寫WFWaterFlowLayout中的四個(gè)方法,顯示出基本的樣式
4.重構(gòu)WFWaterFlowLayout方法必指,讓其性能更高
5.計(jì)算cell的尺寸囊咏,核心計(jì)算
6.顯示數(shù)據(jù)
7.對(duì)項(xiàng)目的接口在做處理,優(yōu)化項(xiàng)目

具體實(shí)現(xiàn)步驟


1.繼承自UICollectionViewLayout創(chuàng)建一個(gè)新的布局對(duì)象WFWaterFlowLayout
import UIKit

class WFWaterFlowLayout: UICollectionViewLayout {

}

2.寫出數(shù)據(jù)源方法取劫,給定colletionView這個(gè)布局
在storyBoard上設(shè)置colletionView和layout
//MARK : - 數(shù)據(jù)源方法
extension WFViewController:UICollectionViewDataSource{
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 50
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(SFImageCellIdent, forIndexPath: indexPath)
        return cell
    }
}
3.重寫WFWaterFlowLayout中的四個(gè)方法,顯示出基本的樣式
import UIKit

class WFWaterFlowLayout: UICollectionViewLayout {

    
    /**
     *  1.初始化調(diào)用的方法
     */
    override func prepareLayout() {
        super.prepareLayout()
    }
    
    /**
     *  2.決定cell展示布局的數(shù)組
     */
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return nil
    }
    
    /**
     *  3.如果你是繼承自“UICollectionViewLayout”的話研侣,那么最好實(shí)現(xiàn)方法谱邪,否則可能出錯(cuò)
         該方法的作用是返回當(dāng)前indexPath位置的布局屬性
     */
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        return nil
    }
    
    /**
     *  4.當(dāng)我們繼承自"UICollectionViewLayout",那么他是不會(huì)滑動(dòng)的,所以我們要給他設(shè)置一個(gè)contenSize來(lái)確定滑動(dòng)的范圍
     */
    override func collectionViewContentSize() -> CGSize {
        return CGSizeMake(0, 100)
    }
    
}
4.重構(gòu)WFWaterFlowLayout方法庶诡,讓其性能更高
  //MARK: - 創(chuàng)建一個(gè)數(shù)組惦银,用來(lái)盛放屬性對(duì)象
    private lazy var attributes = [UICollectionViewLayoutAttributes]()
    
    /**
     *  1.初始化調(diào)用的方法
     */
    override func prepareLayout() {
        super.prepareLayout()
        //每一次調(diào)用reload方法,如果數(shù)組不刪除,那么會(huì)越來(lái)越多數(shù)據(jù)扯俱,所以我們要去清空
        attributes.removeAll()
        
        //2.1 創(chuàng)建含有屬性的數(shù)組
        //流水布局一般是有1組书蚪,我們直接獲取個(gè)數(shù)就好
        let count = collectionView?.numberOfItemsInSection(0)
        
        for index in 0 ..< count!
        {
            //2.2 創(chuàng)建位置
            let indexPath = NSIndexPath.init(forItem: index, inSection: 0)
            //2.3 創(chuàng)建布局屬性
            let  attri = UICollectionViewLayoutAttributes(forCellWithIndexPath:indexPath)
            //2.4 設(shè)置屬性,給frame一個(gè)隨機(jī)數(shù)
            let aX = CGFloat(arc4random_uniform(300))
            let aY = CGFloat(arc4random_uniform(300))
            let aW = CGFloat(arc4random_uniform(300))
            let aH = CGFloat(arc4random_uniform(300))
            attri.frame = CGRectMake( aX, aY, aW, aH)
            attributes.append(attri)
        }
    }
    
    /**
     *  2.決定cell展示布局的數(shù)組
     */
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attributes
    }
    
    /**
     *  3.如果你是繼承自“UICollectionViewLayout”的話迅栅,那么最好實(shí)現(xiàn)方法殊校,否則可能出錯(cuò)
         該方法的作用是返回當(dāng)前indexPath位置的布局屬性
     */
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        return attributes[indexPath.row]
    }
    
    /**
     *  4.當(dāng)我們繼承自"UICollectionViewLayout",那么他是不會(huì)滑動(dòng)的,所以我們要給他設(shè)置一個(gè)contenSize來(lái)確定滑動(dòng)的范圍
     */
    override func collectionViewContentSize() -> CGSize {
        return CGSizeMake(10, 100)
    }

剛才搞錯(cuò)了一個(gè)方法let indexPath = NSIndexPath.init(forItem: index, inSection: 0)读存,寫錯(cuò)成了let indexPath = NSIndexPath(index:index)一直報(bào)錯(cuò)

2016-09-16 14:33:08.890 WaterFlow[2721:225067] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0x7febfa61c680> {length = 1, path = 0}'

一定要注意哈

現(xiàn)在的樣子

注意:今天沒有重寫shouldInvalidateLayoutForBoundsChange這個(gè)方法为流,是因?yàn)椋覀兝^承的是collectionViewLayout让簿,默認(rèn)是真敬察,之前調(diào)用,是因?yàn)槔^承的是UICollectionViewFlowLayout尔当,設(shè)置的是假

5.計(jì)算cell的尺寸莲祸,計(jì)算每一列的高度

步驟
1.獲取collectionView的內(nèi)邊距,item之間的間距等
2.計(jì)算cell的寬度椭迎,隨機(jī)給他一個(gè)高度
3.通過(guò)一個(gè)數(shù)組锐帜,保存所有列的高度,用于比較最小的y值和更新 contentSize

定義幾個(gè)常量

let WFVerticalMargin:CGFloat = 10
let WFHorMargin:CGFloat = 10
let WFEdgeInsets:UIEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)

//oc中這寫
/** 邊緣間距 */
static const UIEdgeInsets WFDefaultEdgeInsets = {10, 10, 10, 10};
// 每一次更新侠碧,我們都要記得刪除過(guò)去的緩存抹估,重新計(jì)算
    override func prepareLayout() {
        super.prepareLayout()
        
        //流水布局一般是有1組,我們直接獲取個(gè)數(shù)就好
        let count = collectionView?.numberOfItemsInSection(0)
        
        //每一次調(diào)用reload方法弄兜,如果數(shù)組不刪除药蜻,那么會(huì)越來(lái)越多數(shù)據(jù),所以我們要去清空
        attributes.removeAll()
        
         /// 1.1 每一次更新替饿,都要先去出緩存的列的高度
        colunmsHeightArr .removeAllObjects()
         /// 1.2 清除之后语泽,還要給他們一個(gè)默認(rèn)的高度
        for _  in 0 ..< count!
        {
               colunmsHeightArr.addObject(WFEdgeInsets.top)
        }
}
 /**
     *  3.如果你是繼承自“UICollectionViewLayout”的話,那么最好實(shí)現(xiàn)方法视卢,否則可能出錯(cuò)
         該方法的作用是返回當(dāng)前indexPath位置的布局屬性
     */
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        let  attri = UICollectionViewLayoutAttributes(forCellWithIndexPath:indexPath)
        
        //1.計(jì)算frame
        
        //2.4 設(shè)置屬性踱卵,給frame一個(gè)隨機(jī)數(shù)
                /// 2.4.1設(shè)置x,y值的根據(jù)就是講cell放置到最小的那一列中
        
         /// 保存最短列的列號(hào) 
        var colunmIndex = 0 //默認(rèn)0
        var colunmMinHeight = colunmsHeightArr[colunmIndex] as! CGFloat//默認(rèn)最短的列高度是第一列
        for col in 1..<WFDefaultColunmsNum {
            let currentColHeight = (colunmsHeightArr[col] as! CGFloat)
            if colunmMinHeight > currentColHeight
            {
                colunmMinHeight = currentColHeight
                colunmIndex = col
            }
        }
        
        
        //幾個(gè)間距的和
        let totalMagin = CGFloat(WFDefaultColunmsNum - 1)*WFHorMargin
        let aW = (WFScreenWidth - WFEdgeInsets.left - WFEdgeInsets.right - totalMagin)/CGFloat(WFDefaultColunmsNum)
        let aH = CGFloat(arc4random_uniform(60)) + 30
        let aX = WFEdgeInsets.left + CGFloat(colunmIndex) * (WFHorMargin + aW)
        
        var aY = colunmMinHeight + WFVerticalMargin
        if aY != WFEdgeInsets.top {
            aY = aY + WFVerticalMargin
        }
        attri.frame = CGRectMake( aX, aY, aW, aH)
        
        //更新保存高度的數(shù)組
        colunmsHeightArr.replaceObjectAtIndex(colunmIndex, withObject: CGRectGetMaxY(attri.frame))
        
        return attri
    }

    /**
     *  4.當(dāng)我們繼承自"UICollectionViewLayout",那么他是不會(huì)滑動(dòng)的据过,所以我們要給他設(shè)置一個(gè)contenSize來(lái)確定滑動(dòng)的范圍
     */
    override func collectionViewContentSize() -> CGSize {
        var maxY = colunmsHeightArr[0] as! CGFloat
        for col in 1..<colunmsHeightArr.count {
            let currentColHeight = (colunmsHeightArr[col] as! CGFloat)
            if maxY < currentColHeight
            {
                maxY = currentColHeight
            }
        }
        
        return CGSizeMake(WFScreenWidth, maxY + WFEdgeInsets.bottom)
    }
}
最后的效果
6.設(shè)置數(shù)據(jù)

使用pod惋砂,設(shè)置框架

platform:ios,'8.0'
use_frameworks!
pod 'MJRefresh'
pod 'SDWebImage'
pod 'MJExtension'

1.生成一個(gè)cell- SFImageCell
2.通過(guò)plist文件來(lái)加載一個(gè)數(shù)組的模型 shops = WFShopModel.mj_objectArrayWithFilename("1.plist")
3.設(shè)置數(shù)據(jù)
4.設(shè)置上啦刷新,下啦加載
5.根據(jù)圖片的寬度绳锅,設(shè)置等比例高度

設(shè)置下啦刷新西饵,上啦加載,注意使用的對(duì)象鳞芙,和延遲兩秒的GCD用法

    private func setupRefreshView(){
      collectionView.mj_header = MJRefreshNormalHeader.init(refreshingBlock: { 

        self.shops.removeAllObjects()
        let data = WFShopModel.mj_objectArrayWithFilename("1.plist")
        self.shops.addObjectsFromArray(data as [AnyObject])
        self.collectionView.reloadData()
        self.collectionView.mj_header.endRefreshing()
      })
        collectionView.mj_footer = MJRefreshAutoNormalFooter.init(refreshingBlock: {
            //要延遲幾秒眷柔,才會(huì)有小菊花
            let time: NSTimeInterval = 2.0
            let delay = dispatch_time(DISPATCH_TIME_NOW,
                Int64(time * Double(NSEC_PER_SEC)))
            dispatch_after(delay, dispatch_get_main_queue()) {
                let data = WFShopModel.mj_objectArrayWithFilename("1.plist")
                self.shops .addObjectsFromArray(data as [AnyObject])
                self.collectionView.reloadData();
                self.collectionView.mj_footer.endRefreshing()
            }
        });
        collectionView.mj_header.beginRefreshing()
        self.collectionView.mj_footer.hidden = false
    }
加載之后期虾,合并數(shù)據(jù)的時(shí)候還是有問(wèn)題,是因?yàn)槲覀儧]有根據(jù)圖片比例設(shè)置寬度

現(xiàn)在去根據(jù)圖片的比例設(shè)置cell 的高度
過(guò)去的高度是 let aH = CGFloat(arc4random_uniform(60)) + 30驯嘱,所以是不對(duì)的

在layout勒種天機(jī)一個(gè)屬性

//計(jì)算cell高度
        let shop = shops?[indexPath.row] as? WFShopModel
        var iHeight:CGFloat =  0
        if shop != nil {
             iHeight =  aW * (shop?.h)!/(shop?.w)!
        }
        let aH = iHeight

在加載數(shù)據(jù)的時(shí)候镶苞,我們都要更新一下shops數(shù)組

//layout 是我從storyBoard上拉線過(guò)來(lái)的,屬于colletionView
        self.layout.shops = self.shops
這就基本寫好了

但是鞠评,現(xiàn)在的只是能夠顯示WFShopModel,在項(xiàng)目中茂蚓,我們稱之為,模塊谢澈,并不能當(dāng)做開源庫(kù)使用煌贴,因?yàn)樗墓δ芴珕我弧?br> 思考?為毛線UITableView功能那么強(qiáng)大锥忿,什么格式都能顯示牛郑,他們?nèi)绾巫龅倪@么強(qiáng)大?因?yàn)橛写砗蛿?shù)據(jù)源敬鬓,現(xiàn)在我們看看如何通過(guò)代理淹朋,給瀑布流拓展成能讓所有人使用的開源庫(kù)


本身可以將所有的方法全部歸類到代理中,但是還是決定使用一個(gè)數(shù)據(jù)源方法钉答,更加直觀础芍。


先寫出來(lái)數(shù)據(jù)源和代理方法,水平有限数尿,google了一些option和必須實(shí)現(xiàn)的方法仑性,但是感覺麻煩,就不寫了右蹦,其實(shí)tableView就有必須實(shí)現(xiàn)诊杆,和可實(shí)現(xiàn)的方法,你們自己找吧~

protocol WFWaterFlowLayoutDataSource:NSObjectProtocol{
    
    /**
     :param: waterFlowLayout self
     :param: width           提供給外邊何陆,cell的寬度
     :returns:返回來(lái)cell 的高度
     */
    func waterFlowLayout(waterFlowLayout: WFWaterFlowLayout, itemWidth width: CGFloat,indexPath:NSIndexPath) -> CGFloat?
    /**
     :param: waterFlowLayout self
     
     :returns: 一共幾列
     */
    func columnOfWaterFlowLayout(waterFlowLayout: WFWaterFlowLayout) -> NSInteger?
}

protocol WFWaterFlowLayoutDelegate:NSObjectProtocol {
    /**
     通過(guò)代理返回過(guò)來(lái)colletionView的內(nèi)邊距
     :param: waterFlowLayout self
     */
     func marginOfSectionInsert(waterFlowLayout: WFWaterFlowLayout) -> UIEdgeInsets?
    /**
     :param: waterFlowLayout self
     
     :returns: 返回item之間豎直間距
     */
    func itemVerticalMargin(waterFlowLayout: WFWaterFlowLayout) -> CGFloat?
    /**
     :param: waterFlowLayout self
     :returns:  返回item之間水平的間距
     */
    func itemHorMargin(waterFlowLayout: WFWaterFlowLayout) -> CGFloat?
    
}

定義一個(gè)代理變量和數(shù)據(jù)源變量晨汹,以及快速獲取變量的值的函數(shù)

    weak var dataSource:WFWaterFlowLayoutDataSource?
    weak var delegate:WFWaterFlowLayoutDelegate?
    
    //MARK - get 方法,獲取具體的數(shù)據(jù)
    private func verticalMarign() -> CGFloat
    {
        if ((delegate?.itemVerticalMargin(self)) != nil)
        {
            return (delegate?.itemVerticalMargin(self))!
        } else{
            return WFVerticalMargin
        }
    }
    
    
    private func horMargin() -> CGFloat
    {
        if ((delegate?.itemHorMargin(self)) != nil) {
            return (delegate?.itemHorMargin(self))!
        }else{
            return WFHorMargin
        }
    }
    
    private func sectionInset() -> UIEdgeInsets{
        if ((delegate?.marginOfSectionInsert(self)) != nil) {
           return (delegate?.marginOfSectionInsert(self))!
        }else{
            return WFEdgeInsets
        }
    }
    
    private func numberOfSection() -> NSInteger{
        if ((dataSource?.columnOfWaterFlowLayout(self)) != nil) {
            return (dataSource?.columnOfWaterFlowLayout(self))!
        }else{
            return WFDefaultColunmsNum
        }
    }

然后將那些東西全部替換,實(shí)現(xiàn)代理方法和數(shù)據(jù)源方法

extension WFViewController:WFWaterFlowLayoutDataSource,WFWaterFlowLayoutDelegate{
    func waterFlowLayout(waterFlowLayout: WFWaterFlowLayout,
                                          itemWidth width: CGFloat,
                                                   indexPath: NSIndexPath) -> CGFloat? {
        let shop = shops[indexPath.row] as! WFShopModel
        return width / (shop.w/shop.h)
    }
    
    func itemHorMargin(waterFlowLayout: WFWaterFlowLayout) -> CGFloat? {
        return 20
    }
    
    func itemVerticalMargin(waterFlowLayout: WFWaterFlowLayout) -> CGFloat? {
        return 30
    }
    
    func columnOfWaterFlowLayout(waterFlowLayout: WFWaterFlowLayout) -> NSInteger? {
        return 3
    }
    
    func marginOfSectionInsert(waterFlowLayout: WFWaterFlowLayout) -> UIEdgeInsets? {
        return UIEdgeInsetsMake(12, 34, 10, 20)
    }
    
}

最后變成了這樣贷盲,實(shí)現(xiàn)了高度的自定義話淘这,其實(shí)和屬性差不多

代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市巩剖,隨后出現(xiàn)的幾起案子铝穷,更是在濱河造成了極大的恐慌,老刑警劉巖佳魔,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙聂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吃引,警方通過(guò)查閱死者的電腦和手機(jī)筹陵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镊尺,“玉大人朦佩,你說(shuō)我怎么就攤上這事÷” “怎么了语稠?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)弄砍。 經(jīng)常有香客問(wèn)我仙畦,道長(zhǎng),這世上最難降的妖魔是什么音婶? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任慨畸,我火速辦了婚禮,結(jié)果婚禮上衣式,老公的妹妹穿的比我還像新娘寸士。我一直安慰自己,他們只是感情好碴卧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布弱卡。 她就那樣靜靜地躺著,像睡著了一般住册。 火紅的嫁衣襯著肌膚如雪婶博。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天荧飞,我揣著相機(jī)與錄音凡人,去河邊找鬼。 笑死垢箕,一個(gè)胖子當(dāng)著我的面吹牛划栓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播条获,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忠荞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了帅掘?” 一聲冷哼從身側(cè)響起委煤,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎修档,沒想到半個(gè)月后碧绞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吱窝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年讥邻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迫靖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兴使,死狀恐怖系宜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情发魄,我是刑警寧澤盹牧,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站励幼,受9級(jí)特大地震影響汰寓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜苹粟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一有滑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嵌削,春花似錦俺孙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至想帅,卻和暖如春场靴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背港准。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工旨剥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浅缸。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓轨帜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親衩椒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚌父,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 問(wèn)答題47 /72 常見瀏覽器兼容性問(wèn)題與解決方案? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,748評(píng)論 1 92
  • 翻譯自“Collection View Programming Guide for iOS” 0 關(guān)于iOS集合視...
    lakerszhy閱讀 3,860評(píng)論 1 22
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,082評(píng)論 25 707
  • 一毛萌、簡(jiǎn)介 學(xué)習(xí)和實(shí)踐Hive中苟弛,使用的都是CLI或者h(yuǎn)ive –e的方式,該方式僅允許使用HiveQL執(zhí)行查詢阁将、更...
    獻(xiàn)給記性不好的自己閱讀 7,428評(píng)論 0 2
  • 簡(jiǎn)介 HashMap是一個(gè)比較常用的鍵值對(duì)集合膏秫,在開發(fā)中常用于映射關(guān)系。以下分析是基于Android中API25下...
    范錦浩閱讀 231評(píng)論 0 0