欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Swift無限循環(huán)控件開發(fā)

 更新時間:2020年07月28日 09:42:12   作者:海闊任月飛  
這篇文章主要為大家詳細(xì)介紹了Swift無限循環(huán)控件開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

無限循環(huán)控件是一個常常用到的一個控件,尤其是一些廣告或者應(yīng)用內(nèi)容公告通知,或者新聞滾動的設(shè)計,都是必備的。這種控件網(wǎng)上也有很多,也有很多可以自定義的版本,功能非常強(qiáng)大。 但對于我們開發(fā)者來說,在具體的應(yīng)用上風(fēng)格和樣式都是比較統(tǒng)一的,一般只需要自己特定的一種風(fēng)格或樣式即可,引入第三方顯然有點(diǎn)大材小用。那么我們怎么能簡單而且又快速的造一個無限循環(huán)的控件呢,只要我們知道無限循環(huán)的原理,那么我們就很自由的按照需求快速的完成。今天我們就講講這個‘造輪'過程。

首先我們簡單分析一下無限循環(huán)的原理。一個控件的自帶滾動有UIScrollView、UICollectionView、UITableView。我們就選這個代表性的控件來講------UICollectionView。他是一個橫向和縱向都可以高度定制的一個控件,而且也遵循Cell重用機(jī)制。

第一步,數(shù)據(jù)倍數(shù)增加,一般為3倍,我們只顯示中間那些數(shù)據(jù)即可,我們向左滑動的時候,滑到中間數(shù)據(jù)的最后一條數(shù)據(jù)的時候繼續(xù)滑動的時候要瞬間換成中間的第一條數(shù)據(jù)。如果向右滑動的時候,如果當(dāng)前是第一條數(shù)據(jù)那么就瞬間移到中間的最后一條數(shù)據(jù)上。這樣看起來就是無限循環(huán)了。一圖勝千言,有圖為證。

滑動原理很簡單,那么我怎么來用代碼實現(xiàn)呢。下面就使用代碼來實現(xiàn)這個控件。

測試環(huán)境:Xcode版本: Version 11.5 (11E608c)    Mac 系統(tǒng):10.15.4 (19E266)

我們先創(chuàng)建一個工程命名為:InfiniteLoopDemo,然后我們在創(chuàng)建一個InfiniteLoopContentView視圖。代碼如下:

import UIKit
 
protocol InfiniteLoopContentViewDelegate: NSObjectProtocol {
 
 func infiniteLoopView(loopView: InfiniteLoopContentView,index: Int) -> UICollectionViewCell;
 func numberCountOfRows(loopView: InfiniteLoopContentView) -> Int;
 func infiniteLoopView(loopView: InfiniteLoopContentView,didSelectedIndexPath index: Int);
 
 func didEndScrollView(loopView: InfiniteLoopContentView) -> Void
}
 
extension InfiniteLoopContentViewDelegate {
 
 func didEndScrollView(loopView: InfiniteLoopContentView) {
 
 }
}
 
class InfiniteLoopContentView: UICollectionView {
 
 private var perContentSize: CGFloat {
 return contentSize.width / 3;
 }
 
 weak var infiniteDelegate: InfiniteLoopContentViewDelegate!
 
 private var perCount = 0;
 
 private var isAutoScroll = false;
 
 private let runDiration: Double = 3.2;
 
 weak fileprivate var pageControl: UIPageControl!
 
 var beginTimer = true {
 didSet{
  runTimer();
 }
 }
 
 private var width: CGFloat {
 frame.width
 }
 private var height: CGFloat {
 frame.height
 }
 
 private func runTimer() -> Void {
 if beginTimer {
  NSObject.cancelPreviousPerformRequests(withTarget: self);
  perform(#selector(runTimerAction), with: nil, afterDelay: runDiration);
 }else {
  NSObject.cancelPreviousPerformRequests(withTarget: self);
  isAutoScroll = false;
 }
 }
 
 
 
 @objc func runTimerAction() -> Void {
 if perCount <= 1 || contentSize.width < self.width {
  return;
 }
 let offsetx = contentOffset.x;
 guard let indexPath = indexPathForItem(at: .init(x: offsetx + width/2, y: height/2)) else{
  return;
 }
 isAutoScroll = true;
 var next = indexPath.row + 1;
 if next >= (perCount * 3 - 1) {
  next = perCount * 3 - 1;
  
  UIView.animate(withDuration: 0.3, animations: { 
  self.scrollToItem(at: .init(row: next, section: 0), at: .centeredHorizontally, animated: false);
  }) { (finished) in
  self.pageControl?.currentPage = self.perCount - 1;
  self.contentOffset = .init(x: (self.perCount - 1) * Int(self.width), y: 0);
  }
  
 }else{
  scrollToItem(at: .init(row: next, section: 0), at: .centeredHorizontally, animated: true);
  pageControl?.currentPage = next % perCount;
 }
 perform(#selector(runTimerAction), with: nil, afterDelay: runDiration);
 
 }
 
 override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
 super.init(frame: frame, collectionViewLayout: layout);
 if let subLayout = layout as? UICollectionViewFlowLayout {
  subLayout.scrollDirection = .horizontal;
  subLayout.minimumLineSpacing = 0;
  subLayout.minimumInteritemSpacing = 0;
  subLayout.itemSize = .init(width: width, height: height);
 }
 showsHorizontalScrollIndicator = false;
 showsVerticalScrollIndicator = false;
 isPagingEnabled = true;
 delegate = self;
 dataSource = self;
 backgroundColor = UIColor.systemBackground;
 
 runTimer();
 }
 
 deinit {
 infiniteDelegate = nil;
 beginTimer = false;
 }
 
 
 required init?(coder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
 
 override func layoutSubviews() {
 super.layoutSubviews();
 
 if perCount <= 1 || isAutoScroll {
  return;
 }
 
 if contentSize.width < self.width {
  return;
 }
 
 
 let contentOffset = self.contentOffset;
 
 if contentOffset.x >= (perContentSize * 2) {
  let offset = contentOffset.x - (perContentSize * 2);
  self.contentOffset = .init(x: perContentSize + offset, y: 0);
 }else if contentOffset.x < perContentSize {
  let offset = Int(contentOffset.x) % Int(perContentSize); 
  self.contentOffset = .init(x: perContentSize + CGFloat(offset), y: 0);
 }
 pageControl?.currentPage = Int((contentOffset.x + width/2) / width) % perCount;
 
 
 }
}
 
extension InfiniteLoopContentView: UICollectionViewDelegateFlowLayout,UICollectionViewDataSource{
 // MARK: - collection view delegate and dataSource
 
 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
 perCount = infiniteDelegate?.numberCountOfRows(loopView: self) ?? 0
 if perCount == 1 {
  return perCount;
 }
 return perCount * 3;
 }
 
 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
 return collectionView.bounds.size;
 }
 
 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
 return infiniteDelegate.infiniteLoopView(loopView: self, index: indexPath.row % perCount);
 }
 
 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
 infiniteDelegate.infiniteLoopView(loopView: self, didSelectedIndexPath: indexPath.row % perCount);
 }
 
}
 
extension InfiniteLoopContentView {
 func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
 beginTimer = false;
 }
 func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
 beginTimer = true;
 infiniteDelegate?.didEndScrollView(loopView: self);
 
 }
 func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
 if !decelerate {
  scrollViewDidEndDecelerating(scrollView);
 }
 }
 func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
 scrollViewDidEndDecelerating(scrollView);
 }
}

這個是循環(huán)的主要代碼,這里需要注意一下如果只有一條數(shù)據(jù)是禁止循環(huán)的。如果需要一張循環(huán),自己可以實現(xiàn)以下。

使用的方法和UICollectionView一樣,我們來看具體使用方式:

import UIKit
 
class MainViewController: UIViewController {
 
 
 
 var loopView: InfiniteLoopContentView!
 
 
 override func viewDidLoad() {
 super.viewDidLoad()
 
 // Do any additional setup after loading the view.
 
 
 let layout = UICollectionViewFlowLayout();
 loopView = InfiniteLoopContentView(frame: .init(x: 0, y: 200, width: view.frame.width, height: 200), collectionViewLayout: layout);
 view.addSubview(loopView);
 loopView.infiniteDelegate = self;
 loopView.register(LoopViewCell.self, forCellWithReuseIdentifier: "cell");
 loopView.reloadData();
 }
 
 
 
}
 
extension MainViewController: InfiniteLoopContentViewDelegate{
 func infiniteLoopView(loopView: InfiniteLoopContentView, index: Int) -> UICollectionViewCell {
 let cell = loopView.dequeueReusableCell(withReuseIdentifier: "cell", for: .init(row: index, section: 0)) as! LoopViewCell;
 cell.imageView.image = UIImage(named: (index + 1).description);
 
 return cell;
 }
 
 func numberCountOfRows(loopView: InfiniteLoopContentView) -> Int {
 return 3;
 }
 
 func infiniteLoopView(loopView: InfiniteLoopContentView, didSelectedIndexPath index: Int) {
 
 }
 
 
}
 
 
class LoopViewCell: UICollectionViewCell {
 var imageView: UIImageView!
 override init(frame: CGRect) {
 super.init(frame: frame);
 imageView = UIImageView(frame: bounds);
 imageView.contentMode = .scaleAspectFit;
 addSubview(imageView);
 backgroundColor = UIColor.black
 }
 
 required init?(coder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
}

這是SwiftUI創(chuàng)建的工程,所以我們可以只用使用最新的Canvars來預(yù)覽效果就好。如下:

struct ContentView: View {
 var body: some View {
 
 ViewController()
 }
}
 
struct ContentView_Previews: PreviewProvider {
 static var previews: some View {
 ContentView()
 }
}
 
struct ViewController: UIViewControllerRepresentable {
 func makeUIViewController(context: Context) -> MainViewController {
 MainViewController()
 }
 
 func updateUIViewController(_ uiViewController: MainViewController, context: Context) {
 
 }
 
 typealias UIViewControllerType = MainViewController 
 
 
}

預(yù)覽的效果如下:

最后上傳上Demo,猛戳這里

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解

    swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解

    這篇文章主要為大家介紹了swiftui開發(fā)之padding默認(rèn)值設(shè)置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • swift實現(xiàn)自動輪播圖效果(UIScrollView+UIPageControl+Timer)

    swift實現(xiàn)自動輪播圖效果(UIScrollView+UIPageControl+Timer)

    這篇文章主要為大家詳細(xì)介紹了swift實現(xiàn)自動輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 判斷?ScrollView List?是否正在滾動詳解

    判斷?ScrollView List?是否正在滾動詳解

    這篇文章主要為大家介紹了判斷?ScrollView、List?是否正在滾動示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Swift使用CoreData時遇到的一些填坑記錄

    Swift使用CoreData時遇到的一些填坑記錄

    這篇文章主要給大家記錄了在Swift使用CoreData時遇到的一些坑,以及介紹了CoreData在Swift 3.0中的一點(diǎn)改變,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-12-12
  • Swift編程之枚舉類型詳解

    Swift編程之枚舉類型詳解

    這篇文章主要介紹了Swift編程之枚舉類型,講解了枚舉語法、匹配枚舉值與switch語句、關(guān)聯(lián)值、原始值等內(nèi)容,Swift中枚舉類型是最重要的類型,感興趣的小伙伴們可以參考一下
    2016-02-02
  • OpenStack的Swift組件詳解

    OpenStack的Swift組件詳解

    這篇文章主要介紹了OpenStack的Swift組件,對swift感興趣的同學(xué),可以參考下
    2021-04-04
  • RxSwift實現(xiàn)替換delegate的方法示例

    RxSwift實現(xiàn)替換delegate的方法示例

    這篇文章主要給大家介紹了關(guān)于RxSwift實現(xiàn)替換delegate的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用RxSwift具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 通過示例分析Swift單例模式

    通過示例分析Swift單例模式

    這篇文章主要介紹了通過示例分析Swift單例模式的三種方法,分別是全局變量,內(nèi)部變量,dispatch_once方式,有需要的小伙伴可以參考下。
    2015-06-06
  • Swift解決UITableView空數(shù)據(jù)視圖問題的簡單方法

    Swift解決UITableView空數(shù)據(jù)視圖問題的簡單方法

    這篇文章主要給大家介紹了關(guān)于Swift解決UITableView空數(shù)據(jù)視圖問題的簡單方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2018-10-10
  • Swift能代替Objective-C嗎?

    Swift能代替Objective-C嗎?

    這是我在網(wǎng)上上看到的答案,復(fù)制粘貼過來和大家分享一下,因為我和很多人一樣很關(guān)心Swift的出現(xiàn)對Mac開發(fā)的影響和對Objective-C的影響。
    2014-09-09

最新評論