Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)
生活随笔
收集整理的這篇文章主要介紹了
Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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画廊效果(左右滑动浏览图片)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库水平切分的实现原理解析——分库,分
- 下一篇: 在vue-cli生成的项目中使用karm