Swift - 使用CollectionView實現圖片Gallery畫廊效果(左右滑動瀏覽圖片)
阿新 • • 發佈:2017-07-25
abs ber pad comment style 即將 使用 ram 數據源
2,畫廊布局類:LinearCollectionViewLayout
(2)主視圖代碼
源碼下載:hangge_1602.zip
原文出自:www.hangge.com 轉載請保留原文鏈接:http://www.hangge.com/blog/cache/detail_1602.html
1,效果圖
(1)圖片從左至右橫向排列(只有一行),通過手指拖動可以前後瀏覽圖片。 (2)視圖滾動時,每張圖片根據其與屏幕中心距離的不同,顯示尺寸也會相應地變化。越靠近屏幕中心尺寸就越大,遠離屏幕中心的就逐漸變小。 (3)滑動結束後,會有位置自動修正的功能。即將當前最靠近屏幕中點的圖片移動到正中央。 (4)點擊圖片則將該圖片刪除,點擊空白處會在最開始的位置插入一張圖片。不管新增還是刪除都有動畫效果。 (5)點擊導航欄上的“切換”按鈕,可以在普通的流式布局和我們自定義的畫廊布局間相互切換。切換時也是有動畫效果的。
2,畫廊布局類:LinearCollectionViewLayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
import UIKit
class LinearCollectionViewLayout : UICollectionViewFlowLayout {
//元素寬度
var itemWidth: CGFloat = 100
//元素高度
var itemHeight: CGFloat = 100
//對一些布局的準備操作放在這裏
override func prepare() {
super .prepare()
//設置元素大小
self .itemSize = CGSize (width: itemWidth, height: itemHeight)
//設置滾動方向
self .scrollDirection = .horizontal
//設置間距
self .minimumLineSpacing = self .collectionView!.bounds.width / 2 - itemWidth
//設置內邊距
//左右邊距為了讓第一張圖片與最後一張圖片出現在最中央
//上下邊距為了讓圖片橫行排列,且只有一行
let left = ( self .collectionView!.bounds.width - itemWidth) / 2
let top = ( self .collectionView!.bounds.height - itemHeight) / 2
self .sectionInset = UIEdgeInsetsMake (top, left, top, left)
}
//邊界發生變化時是否重新布局(視圖滾動的時候也會觸發)
//會重新調用prepareLayout和調用
//layoutAttributesForElementsInRect方法獲得部分cell的布局屬性
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect ) -> Bool {
return true
}
//rect範圍下所有單元格位置屬性
override func layoutAttributesForElements( in rect: CGRect )
-> [ UICollectionViewLayoutAttributes ]? {
//從父類得到默認的所有元素屬性
let array = super .layoutAttributesForElements( in : rect)
//可見區域(目前顯示出來的位於collection view上的矩形區域)
let visiableRect = CGRect (x: self .collectionView!.contentOffset.x,
y: self .collectionView!.contentOffset.y,
width: self .collectionView!.frame.width,
height: self .collectionView!.frame.height)
//當前屏幕中點,相對於collect view上的x坐標
let centerX = self .collectionView!.contentOffset.x
+ self .collectionView!.bounds.width / 2
//這個是為了計算縮放比例的
let maxDeviation = self .collectionView!.bounds.width / 2 + itemWidth / 2
for attributes in array! {
//與可見區域做碰撞,如果該單元格沒顯示則直接跳過
if !visiableRect.intersects(attributes.frame) { continue }
//顯示的單元根據偏移量決定放大倍數(最大放大1.8倍,而離屏幕中央越遠的單元格縮放的越小)
let scale = 1 + (0.8 - abs(centerX - attributes.center.x) / maxDeviation)
attributes.transform = CGAffineTransform (scaleX: scale, y: scale)
}
return array
}
/**
用來設置collectionView停止滾動那一刻的位置(實現目的是當停止滑動,時刻有一張圖片是位於屏幕最中央的)
proposedContentOffset: 原本collectionView停止滾動那一刻的位置
velocity:滾動速度
返回:最終停留的位置
*/
override func targetContentOffset(forProposedContentOffset
proposedContentOffset: CGPoint , withScrollingVelocity velocity: CGPoint ) -> CGPoint {
//停止滾動時的可見區域
let lastRect = CGRect (x: proposedContentOffset.x, y: proposedContentOffset.y,
width: self .collectionView!.bounds.width,
height: self .collectionView!.bounds.height)
//當前屏幕中點,相對於collect view上的x坐標
let centerX = proposedContentOffset.x + self .collectionView!.bounds.width * 0.5;
//這個可見區域內所有的單元格屬性
let array = self .layoutAttributesForElements( in : lastRect)
//需要移動的距離
var adjustOffsetX = CGFloat ( MAXFLOAT );
for attri in array! {
//每個單元格裏中點的偏移量
let deviation = attri.center.x - centerX
//保存偏移最小的那個
if abs(deviation) < abs(adjustOffsetX) {
adjustOffsetX = deviation
}
}
//通過偏移量返回最終停留的位置
return CGPoint (x: proposedContentOffset.x + adjustOffsetX, y: proposedContentOffset.y)
}
}
|
3,使用樣例
(1)自定義單元格類:MyCollectionViewCell.swift(創建的時候生成對應的 xib 文件)1 2 3 4 5 6 7 8 9 10 11 12 |
import UIKit
//自定義的Collection View單元格
class MyCollectionViewCell : UICollectionViewCell {
//用於顯示圖片
@IBOutlet weak var imageView: UIImageView !
override func awakeFromNib() {
super .awakeFromNib()
}
}
|
(2)主視圖代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import UIKit
class ViewController : UIViewController {
//普通的flow流式布局
var flowLayout: UICollectionViewFlowLayout !
//自定義的線性布局
var linearLayput: LinearCollectionViewLayout !
var collectionView: UICollectionView !
//重用的單元格的Identifier
let CellIdentifier = "myCell"
//所有書籍數據
var images = [ "c#.png" , "html.png" , "java.png" , "js.png" , "php.png" ,
"react.png" , "ruby.png" , "swift.png" , "xcode.png" ]
override func viewDidLoad() {
super .viewDidLoad()
//初始化Collection View
initCollectionView()
//註冊tap點擊事件
let tapRecognizer = UITapGestureRecognizer (target: self ,
action: #selector( ViewController .handleTap(_:)))
collectionView.addGestureRecognizer(tapRecognizer)
}
private func initCollectionView() {
//初始化flow布局
flowLayout = UICollectionViewFlowLayout ()
flowLayout.itemSize = CGSize (width: 60, height: 60)
flowLayout.sectionInset = UIEdgeInsets (top: 74, left: 0, bottom: 0, right: 0)
//初始化自定義布局
linearLayput = LinearCollectionViewLayout ()
//初始化Collection View
collectionView = UICollectionView (frame: view.bounds,
collectionViewLayout: linearLayput)
//Collection View代理設置
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = .white
//註冊重用的單元格
let cellXIB = UINib . init (nibName: "MyCollectionViewCell" , bundle: Bundle .main)
collectionView.register(cellXIB, forCellWithReuseIdentifier: CellIdentifier )
//將Collection View添加到主視圖中
view.addSubview(collectionView)
}
//點擊手勢響應
func handleTap(_ sender: UITapGestureRecognizer ){
if sender.state == UIGestureRecognizerState .ended{
let tapPoint = sender.location( in : self .collectionView)
//點擊的是單元格元素
if let indexPath = self .collectionView.indexPathForItem(at: tapPoint) {
//通過performBatchUpdates對collectionView中的元素進行批量的插入,刪除,移動等操作
//同時該方法觸發collectionView所對應的layout的對應的動畫。
self .collectionView.performBatchUpdates({ () -> Void in
self .collectionView.deleteItems(at: [indexPath])
self .images.remove(at: indexPath.row)
}, completion: nil )
}
//點擊的是空白位置
else {
//新元素插入的位置(開頭)
let index = 0
images.insert( "xcode.png" , at: index)
self .collectionView.insertItems(at: [ IndexPath (item: index, section: 0)])
}
}
}
//切換布局樣式
@IBAction func changeLayout(_ sender: Any ) {
self .collectionView.collectionViewLayout.invalidateLayout()
//交替切換新布局
let newLayout = collectionView.collectionViewLayout
.isKind(of: LinearCollectionViewLayout . self ) ? flowLayout : linearLayput
collectionView.setCollectionViewLayout(newLayout!, animated: true )
}
override func didReceiveMemoryWarning() {
super .didReceiveMemoryWarning()
}
}
//Collection View數據源協議相關方法
extension ViewController : UICollectionViewDataSource {
//獲取分區數
func numberOfSections( in collectionView: UICollectionView ) -> Int {
return 1
}
//獲取每個分區裏單元格數量
func collectionView(_ collectionView: UICollectionView ,
numberOfItemsInSection section: Int ) -> Int {
return images.count
}
//返回每個單元格視圖
func collectionView(_ collectionView: UICollectionView ,
cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell {
//獲取重用的單元格
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
CellIdentifier , for : indexPath) as ! MyCollectionViewCell
//設置內部顯示的圖片
cell.imageView.image = UIImage (named: images[indexPath.item])
return cell
}
}
//Collection View樣式布局協議相關方法
extension ViewController : UICollectionViewDelegate {
}
|
原文出自:www.hangge.com 轉載請保留原文鏈接:http://www.hangge.com/blog/cache/detail_1602.html
Swift - 使用CollectionView實現圖片Gallery畫廊效果(左右滑動瀏覽圖片)