UIKit框架(三) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.10.30 星期二

前言

iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面,用戶交互也是通過(guò)UIKit進(jìn)行的泪幌。感興趣的參考上面幾篇文章。
1. UIKit框架(一) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(一)
2. UIKit框架(二) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(二)

開(kāi)始

首先看一下寫(xiě)作環(huán)境。

Swift 4.2, iOS 12, Xcode 10

我們接著看一下要實(shí)現(xiàn)的效果唧瘾。

當(dāng)Apple在2012年在iOS 6中推出collection views時(shí)措译,許多人認(rèn)為它們是解決路障和定制table views的局限性的答案。 有些人甚至建議棄用UITableView饰序。

UICollectionView是一種功能強(qiáng)大且極其靈活的方式领虹,可在您的應(yīng)用中顯示數(shù)據(jù)。 但是求豫,一個(gè)缺點(diǎn)是塌衰,如果沒(méi)有一定程度的自定義,您的應(yīng)用程序看起來(lái)很乏味蝠嘉,并且無(wú)法在App Store中的數(shù)百萬(wàn)個(gè)應(yīng)用程序中脫穎而出最疆。

在本教程中,您將采用一個(gè)相當(dāng)簡(jiǎn)單的“模板化”應(yīng)用程序蚤告,使用不同顏色的items努酸,并將其轉(zhuǎn)換為一種視覺(jué)上令人愉悅的方式。

你將添加令人敬畏的視差效果和一個(gè)特別的cell item杜恰,以及涉及微妙的褪色和過(guò)渡获诈,使其真正脫穎而出的其他應(yīng)用程序。 最終結(jié)果是外觀和感覺(jué)類似于UltraVisual應(yīng)用程序心褐。 如果你還沒(méi)有看到它舔涎,現(xiàn)在就去吧 - 它是免費(fèi)的!

打開(kāi)準(zhǔn)備好的Ultravisual Kit項(xiàng)目檬寂。 在Xcode 10中打開(kāi)Starter項(xiàng)目终抽。在里面,您將找到一個(gè)包含多個(gè)類的簡(jiǎn)單sb項(xiàng)目桶至。 它們可以方便地分成文件夾昼伴,以幫助您瀏覽項(xiàng)目。

這些文件夾包含以下內(nèi)容:

  • Assets:包含Images.xcassets镣屹,Inspirations.plistInspirations.xcassets圃郊,應(yīng)用程序用于加載揚(yáng)聲器的圖像。
  • Controllers:包含InspirationsViewController.swift女蜈,一個(gè)UICollectionViewController子類持舆。
  • Extensions:包含UIColor + Palette.swiftUIImage + Decompression.swift,它們分別提供處理顏色轉(zhuǎn)換和圖像解壓縮的便捷方法伪窖。入門(mén)項(xiàng)目使用調(diào)色板逸寓,在將來(lái)的步驟中,您將切換到使用圖像和解壓縮方法覆山。
  • Layouts:包含UltravisualLayout.swift竹伸,這是該項(xiàng)目的核心。作為UICollectionViewLayout的子類簇宽,UICollectionView要求此類提供有關(guān)如何正確布局和將項(xiàng)item置在collection view中的定義勋篓。在里面吧享,您將找到一組常量和便捷方法,您將使用它們來(lái)簡(jiǎn)化布局設(shè)置譬嚣。此外钢颂,它還提供了一個(gè)簡(jiǎn)單的UICollectionViewLayoutAttributes自定義緩存,用于修改每個(gè)單元格拜银。
  • Models:包含背景圖像(Inspiration.swift)和會(huì)話詳細(xì)信息(Session.swift)的數(shù)據(jù)模型殊鞭;他們分開(kāi)進(jìn)行最終的MVC模式勝利!
  • Views:包含InspirationCell.swift盐股,它處理設(shè)置collection view cell的屬性钱豁。

構(gòu)建并運(yùn)行入門(mén)項(xiàng)目,您將看到以下內(nèi)容:

該應(yīng)用程序看起來(lái)不錯(cuò)(如果你想要一個(gè)隨機(jī)的調(diào)色板應(yīng)用程序疯汁,這就是)牲尺,但它現(xiàn)在沒(méi)有做太多。 這就是你的工作所在:你會(huì)把這個(gè)笨蛋變成一個(gè)漂亮的應(yīng)用程序幌蚊,旨在快速瀏覽RD的鼓舞人心的演講者和主題列表谤碳。

該項(xiàng)目的技術(shù)魔力來(lái)自管理不同的cell item狀態(tài):

  • 標(biāo)準(zhǔn)單元格(您在入門(mén)項(xiàng)目中看到的)轉(zhuǎn)換為“下一個(gè)”單元格,該單元格會(huì)變大一些溢豆。
  • 特色cell蜒简,是所有cell中最大的。

您還將使用一些小技巧 - 在滾動(dòng)時(shí)修改單元格的z-index以獲得甜蜜的堆疊效果漩仙。


Creating Multiple Cell Sizes - 創(chuàng)建多個(gè)單元格大小

首先搓茬,您將創(chuàng)建特色單元格。 它大約是標(biāo)準(zhǔn)單元格的兩倍队他,因此用戶可以清楚地看到選擇了哪個(gè)項(xiàng)目卷仑。

跳轉(zhuǎn)到UltravisualLayout.swift并轉(zhuǎn)到prepare()。 在這行代碼之后:

cache.removeAll(keepingCapacity: false)

添加一些您將在每個(gè)item中使用的新局部變量:

let standardHeight = UltravisualLayoutConstants.Cell.standardHeight
let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight
  
var frame = CGRect.zero
var y: CGFloat = 0    

接下來(lái)麸折,添加以下代碼以遍歷collection view中的每個(gè)item并相應(yīng)地調(diào)整item的狀態(tài):

for item in 0..<numberOfItems {
  // 1
  let indexPath = IndexPath(item: item, section: 0)
  let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
  
  // 2
  attributes.zIndex = item
  var height = standardHeight
  
  // 3
  if indexPath.item == featuredItemIndex {
    // 4
    let yOffset = standardHeight * nextItemPercentageOffset
    y = collectionView!.contentOffset.y - yOffset
    height = featuredHeight
  } else if indexPath.item == (featuredItemIndex + 1)
    && indexPath.item != numberOfItems {
    // 5
    let maxY = y + standardHeight
    height = standardHeight + max(
      (featuredHeight - standardHeight) * nextItemPercentageOffset, 0
    )
    y = maxY - height
  }
  
  // 6
  frame = CGRect(x: 0, y: y, width: width, height: height)
  attributes.frame = frame
  cache.append(attributes)
  y = frame.maxY
}

下面進(jìn)行詳細(xì)說(shuō)明:

  • 1) 創(chuàng)建當(dāng)前單元格的索引路徑锡凝,然后為其創(chuàng)建默認(rèn)屬性。
  • 2) 準(zhǔn)備cell向上或向下移動(dòng)垢啼。由于大多數(shù)細(xì)胞不具備特征 - 標(biāo)準(zhǔn)cell比單一特征cell多得多 - 它默認(rèn)為standardHeight窜锯。
  • 3) 確定當(dāng)前單元格的狀態(tài) - featured, next or standard。就后者而言芭析,你什么都不做锚扎。
  • 4) 如果單元格當(dāng)前處于特征單元格位置,則計(jì)算yOffset并使用該值來(lái)導(dǎo)出單元格的新y值馁启。之后驾孔,將單元格的高度設(shè)置為特征高度。
  • 5) 如果單元格在下一行,則首先計(jì)算最大y可能(在這種情況下助币,大于特征單元格)并將其與計(jì)算高度相結(jié)合,最終得到正確的y值螟碎,即280.0 - 特色cell的高度眉菱。
  • 6) 最后,為每個(gè)單元格設(shè)置一些公共元素掉分,包括創(chuàng)建frame俭缓,設(shè)置計(jì)算的屬性以及更新緩存值。最后一步是更新y酥郭,使其位于最后一個(gè)計(jì)算單元格的底部华坦,以便您可以有效地向下移動(dòng)單元格列表。

要使collection view知道要使用哪個(gè)布局不从,您需要告訴UICollectionView使用UltravisualLayout作為其布局類惜姐。

首先,打開(kāi)Main.storyboard并選擇Document Outline中的Collection View椿息。

接下來(lái)歹袁,打開(kāi)Attributes inspector并將Layout下拉列表設(shè)置為Custom,然后將Class設(shè)置為UltravisualLayout寝优。

最后条舔,在構(gòu)建之前,轉(zhuǎn)到InspirationsViewController.swift乏矾,并在viewDidLoad()中刪除最后兩行:

let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: collectionView!.bounds.width, height: 100)

這兩行是顯示同樣大小的多色單元格的基本布局孟抗。 現(xiàn)在您已經(jīng)在UltravisualLayout中指定了布局代碼并在故事板中設(shè)置了自定義布局類,您不再需要這些行钻心。

構(gòu)建并運(yùn)行凄硼,你會(huì)看到:

請(qǐng)注意,頂部單元格要大得多扔役,有效地展示了一個(gè)特色單元格帆喇。滾動(dòng)時(shí),特色單元格下方的單元格會(huì)擴(kuò)展并重疊當(dāng)前的特征單元格亿胸。多棒的效果坯钦!


Adding Cell Images - 添加cell圖像

有色單元格很棒,但這里要求不能用彩色表示侈玄!

入門(mén)項(xiàng)目包括一組要使用的圖像婉刀。 (如果你想快速瀏覽一下,他們就在Inspirations.xcassets中)序仙。

但是你不能以任何舊的方式使用它們 - 如果你正在做這個(gè)教程突颊,那么,顯然,你就是那種令人喜歡的用戶體驗(yàn)律秃。

不僅是時(shí)候用圖像替換顏色了爬橡,而且你將以這樣的方式這樣做:當(dāng)用戶將單元格滾動(dòng)到特色單元格時(shí),圖像實(shí)際上會(huì)顯示更多棒动。

首先糙申,將新圖像視圖添加到集合視圖單元格。轉(zhuǎn)到Main.storyboard船惨,選擇InspirationCell柜裸,然后將其調(diào)整為200?200。這不是絕對(duì)必要的粱锐,但它可以幫助您直觀地看到比標(biāo)準(zhǔn)單元格大小更容易發(fā)生的事情疙挺。

接下來(lái),打開(kāi)Identity inspector并將Class類型設(shè)置為InspirationCell怜浅。

然后铐然,將UIImageView對(duì)象從Xcode 10 Library拖放到單元格上。 選擇剛剛添加的UIImageView恶座,轉(zhuǎn)到Attributes inspector并將Content Mode更改為Aspect Fill锦爵。

現(xiàn)在有一些自動(dòng)布局約束:選擇布局視圖底部的Add New Constraints菜單,并按如下所示設(shè)置約束:

  • 取消選中Constrain to Margins奥裸。
  • leading and trailing spaces設(shè)置為0险掀。
  • 檢查Height并將其值設(shè)置為280(特征單元格的高度)。
  • 單擊Apply 3 New Constraints湾宙。

它應(yīng)該看起來(lái)像這樣:

Align菜單(位于Pin菜單左側(cè))中選擇Vertically in Container并應(yīng)用該單個(gè)約束樟氢。

這樣可以創(chuàng)建一個(gè)很酷的效果,使圖像在圖像視圖中居中侠鳄,與特征單元格的整個(gè)高度成比例埠啃,但它會(huì)被標(biāo)準(zhǔn)單元格高度掩蓋,直到單元格完全在視圖中伟恶。

最后碴开,通過(guò)右鍵單擊Document Outline中的InspirationCell并將imageViewoutlet連接到剛剛添加的UIImageView來(lái)添加outlet連接。

跳轉(zhuǎn)到InspirationsViewController.swift并用以下內(nèi)容替換collectionView(_:cellForItemAt :)的實(shí)現(xiàn):

guard let cell = collectionView.dequeueReusableCell(
  withReuseIdentifier: InspirationCell.reuseIdentifier, for: indexPath)
  as? InspirationCell else {
    return UICollectionViewCell()
}
cell.inspiration = inspirations[indexPath.item]
return cell

由于您在Interface Builder中設(shè)置了單元格的類博秫,因此您可以在出列調(diào)用中轉(zhuǎn)換為InspirationsCell潦牛。 您可以將單元格的inspiration屬性設(shè)置為所有inspirations數(shù)組中的正確條目,而不是設(shè)置單元格的背景顏色挡育。

最后巴碗,在文件的頂部,刪除colors數(shù)組的定義即寒,因?yàn)槟辉傩枰?/p>

建立和運(yùn)行 - 看到純粹的形象榮耀橡淆!


Featuring Featured Cells - 特色cell

新的圖像看起來(lái)很棒召噩,但有一點(diǎn)你會(huì)注意到,無(wú)論它們?cè)诹斜碇械哪膫€(gè)位置逸爵,所有圖像都在爭(zhēng)奪你的注意力具滴。

實(shí)際上,只有特色cell才能引起你的注意师倔。

接下來(lái)抵蚊,您將添加一個(gè)簡(jiǎn)單的UIView疊加層來(lái)管理每個(gè)單元格的不透明度。 這一次溯革,你將使用的詭計(jì)是一個(gè)掩模,當(dāng)cell離開(kāi)特征視圖時(shí)變暗cell谷醉,當(dāng)它們靠近頂部時(shí)變亮致稀。

返回Main.storyboard并在之前添加的UIImageView下添加UIView。

Add New Constraints菜單中俱尼,取消選中Constrain to margins(如果已選中)抖单,此時(shí),將所有四個(gè)Spacing to nearest neighbor值設(shè)置為0遇八,然后選擇Add 4 Constraints矛绘。

接下來(lái),將InspirationCellimageCoverView outlet連接到剛剛添加的UIView刃永。 再次選擇視圖货矮,然后在Attributes inspector中,將Background Color設(shè)置為Black Color斯够。

現(xiàn)在您已經(jīng)設(shè)置了UI來(lái)屏蔽圖像囚玫,現(xiàn)在是時(shí)候在代碼中更新mask了。

轉(zhuǎn)到Views文件夾中的InspirationCell.swift并將以下方法添加到類中:

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
  super.apply(layoutAttributes)
  
  // 1
  let standardHeight = UltravisualLayoutConstants.Cell.standardHeight
  let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight
  
  // 2
  let delta = 1 - (
    (featuredHeight - frame.height) / (featuredHeight - standardHeight)
  )
  
  // 3
  let minAlpha: CGFloat = 0.3
  let maxAlpha: CGFloat = 0.75
  imageCoverView.alpha = maxAlpha - (delta * (maxAlpha - minAlpha))
}

此方法在渲染和向上或向下移動(dòng)屏幕時(shí)更新應(yīng)用于單元格的效果读规。 下面進(jìn)行細(xì)分:

  • 1) 這些是您之前使用過(guò)的兩個(gè)便捷性高度常數(shù)抓督。
  • 2) 計(jì)算單元格移動(dòng)時(shí)的增量,以計(jì)算在下一步中調(diào)整alpha的程度束亏。
  • 3) 根據(jù)范圍常量铃在,根據(jù)delta值更新單元格的alpha。

delta的計(jì)算范圍為0到1碍遍,因?yàn)樗_定了從標(biāo)準(zhǔn)高度到特征高度單元格的高度變化百分比定铜。 從那里,α可以計(jì)算為應(yīng)用于可接受的α范圍的百分比delta怕敬,在這個(gè)例子中宿稀,該范圍在0.3和0.75之間。

構(gòu)建并運(yùn)行赖捌!


Adding Session Details - 添加會(huì)議細(xì)節(jié)

在這一點(diǎn)上祝沸,你的圖像看起來(lái)很棒矮烹,具有微妙的視差效果和alpha透明度。

但是在你太興奮之前罩锐,請(qǐng)記住奉狈,只有一個(gè)問(wèn)題:如果沒(méi)有會(huì)議的文本內(nèi)容,時(shí)間和空間涩惑,圖像只不過(guò)是漂亮的圖片仁期! 你接下來(lái)會(huì)添加這些。

首先竭恬,將會(huì)話標(biāo)題添加到每個(gè)item跛蛋。 打開(kāi)Main.storyboard并將UILabel從Library拖到Document Outline中的InspirationCell上。 確保UILabel是作為兄弟視圖創(chuàng)建的痊硕,這意味著它在Image ViewView的層次結(jié)構(gòu)中處于同一級(jí)別赊级。

選擇label,然后在Attributes inspector中進(jìn)行以下更改:

  • 將Text設(shè)置為Inspiration岔绸。
  • Color設(shè)置為White Color理逊。
  • Font設(shè)置為CustomFamily設(shè)置為Avenir Next盒揉,使用Demi Bold樣式和38的Size晋被。
  • Alignment設(shè)置為Center

在標(biāo)簽仍處于選中狀態(tài)的情況下刚盈,單擊Interface Builder右下角的Add New Constraints按鈕羡洛。 在彈出窗口中,確保取消選中Constrain to margins藕漱,然后添加以下布局約束:

  • 選擇Leading Space并將常量設(shè)置為0翘县。
  • 選擇Trailing Space并將常量設(shè)置為0。
  • 選擇Height并將常量設(shè)置為44谴分。

選擇Add 3 Constraints锈麸。

最后,單擊Align按鈕牺蹄,選擇Vertically in Container忘伞,然后選擇Add 1 Constraint

您的單元格現(xiàn)在應(yīng)該如下所示:

接下來(lái),您必須將新label連接到單元格沙兰,以便您可以正確設(shè)置文本氓奈。 打開(kāi)InspirationCell.swift并在聲明imageCoverView后立即添加一個(gè)新屬性:

@IBOutlet private weak var titleLabel: UILabel!

然后,在didSet的if塊內(nèi)鼎天,添加:

titleLabel.text = inspiration.title

這可確保每次屬性值更改時(shí)label的文本都會(huì)更新舀奶。

跳回Main.storyboard并右鍵單擊Document Outline中的InspirationCell以顯示連接彈出窗口。 從titleLabel拖動(dòng)到剛剛創(chuàng)建的標(biāo)簽以連接兩者:

構(gòu)建和運(yùn)行 - 看看那些甜蜜斋射,甜蜜的會(huì)議標(biāo)題育勺!

你知道什么會(huì)對(duì)標(biāo)題標(biāo)簽產(chǎn)生很好的影響嗎但荤? 讓它們按用戶滾動(dòng)縮放!


Scaling Cells - 縮放Cell

打開(kāi)InspirationCell.swift并將以下內(nèi)容添加到apply(_ :)的底部:

let scale = max(delta, 0.5)
titleLabel.transform = CGAffineTransform(scaleX: scale, y: scale)

在這里涧至,你創(chuàng)建一個(gè)常數(shù)腹躁,它是兩者中的中的較大值: delta - 如果你還記得的話,它是0到1之間的值 - 和0.5; 這很重要南蓬,因?yàn)槟幌M麡?biāo)簽縮放到小于其全尺寸的一半纺非。

接下來(lái),使用CGAffineTransform(scaleX:y :)創(chuàng)建通過(guò)其transform屬性在label上設(shè)置的縮放變換赘方。

構(gòu)建并運(yùn)行烧颖。 您將看到標(biāo)準(zhǔn)單元格中的會(huì)議標(biāo)題是特征單元格中標(biāo)題大小的一半,并且隨著標(biāo)準(zhǔn)單元格轉(zhuǎn)換為特征單元格窄陡,標(biāo)簽會(huì)平滑縮放:

現(xiàn)在炕淮,是時(shí)候?qū)⑹S嗟臅?huì)議細(xì)節(jié)添加到單元格中,并在用戶滾動(dòng)時(shí)使它們淡入視圖泳梆。


Adding Session Details - 添加會(huì)議細(xì)節(jié)

打開(kāi)Main.storyboard并從庫(kù)中將另外兩個(gè)label拖到Document Outline中的單元格上。 再次確保它們是作為其他視圖的兄弟視圖而不是作為子視圖創(chuàng)建的榜掌。

更新的Document Outline應(yīng)如下所示:

使用Attributes inspector优妙,將其中一個(gè)標(biāo)簽的“文本”設(shè)置為Time, Room,將另一個(gè)標(biāo)簽設(shè)置為Speaker憎账。然后對(duì)它們進(jìn)行以下更改:

  • Color設(shè)置為White Color套硼。
  • Font設(shè)置為Custom,將Family設(shè)置為Avenir Next胞皱,使用Medium和17的Size邪意。
  • Alignment設(shè)置為Center

在故事板畫(huà)布中反砌,拖動(dòng)Inspiration標(biāo)簽下方的Time雾鬼,Room標(biāo)簽。然后拖動(dòng)Time宴树,Room標(biāo)簽下面的Speaker標(biāo)簽策菜,使它們看起來(lái)堆疊在一起。

選擇Time酒贬,Room標(biāo)簽又憨,然后單擊Add New Constraints按鈕。確保取消選中Constrain to margin锭吨,然后添加以下布局約束:

  • 選擇Leading并將約束設(shè)置為0蠢莺。
  • 選擇Top并將約束設(shè)置為0 - 通過(guò)單擊下拉箭頭確保它引用Inspiration (Title Label)Bottom
  • 選擇Trailing并將常量設(shè)置為0零如。

單擊Add 3 Constraints躏将。

現(xiàn)在锄弱,選擇Speaker標(biāo)簽并添加相同的布局約束,但這次確保Top space引用Time耸携,Room而不是InspirationInspirationCell棵癣。

如果您在下拉列表中難以獲得正確的值,請(qǐng)嘗試在視圖中稍微向下移動(dòng)標(biāo)簽夺衍,例如10px狈谊,然后再次查看下拉列表。視圖必須有足夠的間距沟沙,以便Interface Builder可以準(zhǔn)確地檢測(cè)您要執(zhí)行的操作河劝。

您的單元格現(xiàn)在應(yīng)如下所示:

跳回到InspirationCell.swift并添加以下outlets,位于其他outlets下方:

@IBOutlet private weak var timeAndRoomLabel: UILabel!
@IBOutlet private weak var speakerLabel: UILabel!

您將使用它們?cè)谙鄳?yīng)的標(biāo)簽上設(shè)置Time, RoomSpeaker詳細(xì)信息矛紫。

現(xiàn)在赎瞎,將以下內(nèi)容添加到inspiration屬性的didSet觀察者內(nèi)的if塊的底部:

timeAndRoomLabel.text = inspiration.roomAndTime
speakerLabel.text = inspiration.speaker

就像之前設(shè)置的titleLabel一樣,這可以確保每當(dāng)inspiration發(fā)生變化時(shí)值都會(huì)更新颊咬。

跳回Main.storyboard并右鍵單擊Document Outline中的InspirationCell以調(diào)用連接彈出窗口务甥。

timeAndRoomLabel拖動(dòng)到中間標(biāo)簽以連接它們,然后從speakerLabel拖動(dòng)到底部標(biāo)簽以連接這兩個(gè)標(biāo)簽喳篇。

構(gòu)建并運(yùn)行敞临。 您將看到會(huì)話詳細(xì)信息現(xiàn)在按預(yù)期顯示,但它們?cè)跇?biāo)準(zhǔn)單元格中看起來(lái)不太正確:

是時(shí)候解決了麸澜!

InspirationCell.swift中挺尿,找到apply(_ :)并將以下內(nèi)容添加到最底層:

timeAndRoomLabel.alpha = delta 
speakerLabel.alpha = delta

您只需將每個(gè)標(biāo)簽的alpha設(shè)置為delta變量,如果您還記得炊邦,該變量表示過(guò)渡到特征單元格的單元格的進(jìn)度编矾。

通過(guò)這樣做,您確保會(huì)話詳細(xì)信息在標(biāo)準(zhǔn)單元格中不可見(jiàn)馁害,但隨著每個(gè)單元格成為特征單元格而淡入窄俏。

再一次,構(gòu)建并運(yùn)行碘菜。 您現(xiàn)在將看到會(huì)話詳細(xì)信息未顯示在標(biāo)準(zhǔn)單元格上裆操,而是在向上滾動(dòng)時(shí)淡入:

真是太美了!


Smooth Scrolling - 平滑滾動(dòng)

你必須做的最后一件事就是讓這個(gè)應(yīng)用程序的UI真的流行起來(lái)炉媒;您將調(diào)整集合視圖滾動(dòng)的方式踪区,以便一個(gè)單元格始終處于屏幕頂部的完全焦點(diǎn)。 這將有助于您的用戶專注于內(nèi)容吊骤,而不是花費(fèi)精力滾動(dòng)到一個(gè)確切的位置缎岗。

打開(kāi)UltravisualLayout.swift并將以下方法添加到類中:

override func targetContentOffset(
  forProposedContentOffset proposedContentOffset: CGPoint,
  withScrollingVelocity velocity: CGPoint) -> CGPoint {
  let itemIndex = round(proposedContentOffset.y / dragOffset)
  let yOffset = itemIndex * dragOffset
  return CGPoint(x: 0, y: yOffset)
}

這是UIScrollView的一種常用方法,它允許您的應(yīng)用以類似于分頁(yè)UIScrollView的頁(yè)面捕捉效果的效果進(jìn)行響應(yīng)白粉。

當(dāng)用戶在滾動(dòng)之后抬起他們的手指传泊,同時(shí)仍然有一些滾動(dòng)速度時(shí)鼠渺,此方法將展望未來(lái),并且由于proposedContentOffset眷细,將告訴您滾動(dòng)將在何處結(jié)束拦盹。 通過(guò)返回不同的滾動(dòng)點(diǎn),您可以使collection view在特征單元格的均勻邊界上結(jié)束溪椎。

您在實(shí)現(xiàn)中所做的只是找到與建議的內(nèi)容偏移量最接近的item普舆,然后返回一個(gè)CGPoint,其位置使得項(xiàng)目將在屏幕頂部正確校读。

默認(rèn)情況下沼侣,滾動(dòng)視圖的減速率相當(dāng)慢,這可能會(huì)使您的目標(biāo)偏移變化看起來(lái)有點(diǎn)奇怪歉秫。 這是一個(gè)簡(jiǎn)單的解決方案蛾洛! 跳轉(zhuǎn)到InspirationsViewController.swift,并在viewDidLoad()中雁芙,將以下代碼添加到方法的末尾:

collectionView?.decelerationRate = .fast

構(gòu)建并運(yùn)行轧膘,你已經(jīng)完成了!


Challenge: Tap to Select - 挑戰(zhàn):點(diǎn)擊選擇

哦兔甘,還有一件事谎碍。 能夠滾動(dòng)該列表非常酷裂明,但您是否注意到點(diǎn)擊一個(gè)單元格時(shí)會(huì)發(fā)生什么椿浓?

那是對(duì)的 - 沒(méi)什么太援。

為什么不將一個(gè)點(diǎn)擊的單元格滾動(dòng)到頂部以使其獲得焦點(diǎn)闽晦? 嘗試添加新功能來(lái)處理點(diǎn)擊事件。 考慮如何處理在UITableView上選擇行以進(jìn)行類似的處理提岔。

InspirationViewController.swift中仙蛉,通過(guò)將以下方法添加到類中,使單元格處理tap事件:

override func collectionView(_ collectionView: UICollectionView,
                             didSelectItemAt indexPath: IndexPath) {
  guard let layout = collectionViewLayout
    as? UltravisualLayout else {
      return
  }
  let offset = layout.dragOffset * CGFloat(indexPath.item)
  if collectionView.contentOffset.y != offset {
    collectionView.setContentOffset(
      CGPoint(x: 0, y: offset), animated: true
    )
  }
}

如果您希望了解有關(guān)自定義布局的更多信息碱蒙,請(qǐng)考慮以下資源:

閱讀Collection View Programming Guide for iOSCreating Custom Layouts部分荠瘪,該部分廣泛涵蓋了此主題。

后記

本篇主要講述了UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)赛惩,感興趣的給個(gè)贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哀墓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喷兼,更是在濱河造成了極大的恐慌篮绰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件季惯,死亡現(xiàn)場(chǎng)離奇詭異吠各,居然都是意外死亡臀突,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)贾漏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)候学,“玉大人,你說(shuō)我怎么就攤上這事纵散∈崧耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵困食,是天一觀的道長(zhǎng)边翁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)硕盹,這世上最難降的妖魔是什么符匾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮瘩例,結(jié)果婚禮上啊胶,老公的妹妹穿的比我還像新娘。我一直安慰自己垛贤,他們只是感情好焰坪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著聘惦,像睡著了一般某饰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上善绎,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天黔漂,我揣著相機(jī)與錄音,去河邊找鬼禀酱。 笑死炬守,一個(gè)胖子當(dāng)著我的面吹牛渠旁,可吹牛的內(nèi)容都是我干的磺陡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舒萎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼曹洽!你這毒婦竟也來(lái)了鳍置?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤送淆,失蹤者是張志新(化名)和其女友劉穎税产,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砖第,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年撤卢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梧兼。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡放吩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出羽杰,到底是詐尸還是另有隱情渡紫,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布考赛,位于F島的核電站惕澎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏颜骤。R本人自食惡果不足惜唧喉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忍抽。 院中可真熱鬧八孝,春花似錦、人聲如沸鸠项。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)祟绊。三九已至楼入,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間牧抽,已是汗流浹背嘉熊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阎姥,地道東北人记舆。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓鸽捻,卻偏偏與公主長(zhǎng)得像呼巴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子御蒲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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