自定義視圖是在項目開發中經常會面臨的工作,通過對視圖進行封裝,能達到更好的複用性,并使得VC裡面的邏輯更加清晰。本篇将對實際項目中常用的圖檔輪播進行封裝。
1.先從源碼看起
首先,定義了一個枚舉類型,用于區分圖檔的存儲類型:網絡圖檔還是本地圖檔。
/**
圖檔存儲類型
- Local: 本地圖檔
- Network: 網絡圖檔
*/
enum GofImageStoreType: Int
{
case Local = 0;
case Network;
}
然後對圖檔輪播類進行了功能封裝。
class GofImageScrollView: UIView
{
/// 圖檔數組
private var arrImage: [String]?;
/// 分頁
private var imgPageControl: UIPageControl?;
/// 按鈕單擊回調Block
private var btnClick: GofBtnClickBlock?;
/// 滾動視圖
private var imgScrollView: UIScrollView?;
/// 計時器
private var timer: NSTimer?;
/// 目前頁索引
private var iCurrentIndex: NSInteger?;
/**
建立GofImageScrollView
- parameter array: 圖檔數組(本地圖檔傳圖檔名稱數組,網絡圖檔傳圖檔URL數組,均為字元串數組)
- parameter storeType: 圖檔存儲類型(網絡圖檔/本地圖檔)
- parameter btnClickBlock: 按鈕單擊處理
- parameter superView: 父視圖
- parameter constraints: 限制
- returns: GofImageScrollView
*/
static func gof_ImageScrollView(array: [String], storeType: GofImageStoreType, btnClickBlock: GofBtnClickBlock?, superView: UIView?, constraints: GofConstraintMaker?) -> GofImageScrollView
{
let scroll = GofImageScrollView();
if superView != nil
{
superView!.addSubview(scroll);
if constraints != nil
{
scroll.snp_makeConstraints(closure: { (make) in
constraints!(make);
})
scroll.showScrollViewWithImageArray(array, storeType: storeType, btnClickBlock: btnClickBlock);
}
}
return scroll;
}
/**
顯示圖檔輪播
- parameter array: 圖檔數組(本地圖檔傳圖檔名稱數組,網絡圖檔傳圖檔URL數組,均為字元串數組)
- parameter storeType: 圖檔存儲類型(網絡圖檔/本地圖檔)
- parameter btnClickBlock: 按鈕單擊處理
*/
func showScrollViewWithImageArray(array: [String], storeType: GofImageStoreType, btnClickBlock: GofBtnClickBlock?)
{
//變量指派
arrImage = array;
btnClick = btnClickBlock;
iCurrentIndex = 1;
//滾動視圖
imgScrollView = UIScrollView.init();
imgScrollView!.delegate = self
imgScrollView!.pagingEnabled = true;
imgScrollView!.contentSize = CGSizeMake(self.bounds.size.width * CGFloat(array.count + 2), 0);
imgScrollView!.contentOffset = CGPointMake(self.bounds.size.width * 2, 0);
imgScrollView!.showsHorizontalScrollIndicator = false;
imgScrollView!.showsVerticalScrollIndicator = false;
self.addSubview(imgScrollView!);
imgScrollView?.snp_makeConstraints(closure: { (make) in
make.edges.equalTo(self);
});
//内容容器視圖
let containerView = UIView();
imgScrollView?.addSubview(containerView);
containerView.snp_makeConstraints { (make) in
make.edges.equalTo(self.imgScrollView!);
make.top.equalTo(0);
make.height.equalTo(self);
}
//分頁小圓點
imgPageControl = UIPageControl.init();
imgPageControl?.numberOfPages = array.count;
imgPageControl?.currentPage = 0;
imgPageControl?.userInteractionEnabled = false;
imgPageControl?.currentPageIndicatorTintColor = UIColor.greenColor();
imgPageControl?.pageIndicatorTintColor = UIColor.grayColor();
self.addSubview(imgPageControl!);
imgPageControl?.snp_makeConstraints(closure: { (make) in
make.left.equalTo(0);
make.top.equalTo(self.snp_bottom).offset(-20);
make.right.equalTo(0);
make.height.equalTo(20);
})
//添加圖檔
for i in 0...array.count - 1
{
//圖檔
let button = UIButton.gof_buttonWithTitle(nil, superView: containerView, constraints: { (make) in
make.leading.equalTo(kScreenWidth * CGFloat(i + 1));
make.top.equalTo(0);
make.width.equalTo(kScreenWidth);
make.bottom.equalTo(0);
}, touchup: { [unowned self] (btn) in
if (self.btnClick != nil)
{
self.btnClick(btn);
}
});
button.tag = 100 + i;
if .Local == storeType
{
button.setImage(gof_ImageWithName(array[i > (array.count - 1) ? 0 : i] ), forState: .Normal);
}
else
{
button.kf_setImageWithURL(NSURL(string: array[i > (array.count - 1) ? 0 : i] ), forState: .Normal);
}
}
//右邊加個圖檔用于過渡
let rightButton = UIButton.gof_buttonWithTitle(nil, superView: containerView, constraints: { (make) in
make.leading.equalTo(kScreenWidth * CGFloat(array.count + 1));
make.top.equalTo(0);
make.width.equalTo(kScreenWidth);
make.bottom.equalTo(0);
}, touchup: { [unowned self] (btn) in
if (self.btnClick != nil)
{
self.btnClick(btn);
}
});
rightButton.tag = 100;
//左邊加個圖檔用于過渡
let leftButton = UIButton.gof_buttonWithTitle(nil, superView: containerView, constraints: { (make) in
make.leading.equalTo(0);
make.top.equalTo(0);
make.width.equalTo(kScreenWidth);
make.bottom.equalTo(0);
}, touchup: { [unowned self] (btn) in
if (self.btnClick != nil)
{
self.btnClick(btn);
}
});
leftButton.tag = 100 + array.count - 1;
containerView.snp_makeConstraints { (make) in
make.right.equalTo(rightButton);
}
if .Local == storeType
{
rightButton.setImage(gof_ImageWithName(array[0]), forState: .Normal);
leftButton.setImage(gof_ImageWithName(array[array.count - 1]), forState: .Normal);
}
else
{
rightButton.kf_setImageWithURL(NSURL(string: array[0]), forState: .Normal);
leftButton.kf_setImageWithURL(NSURL(string: array[array.count - 1]), forState: .Normal);
}
self.startScrollForInit();
}
/**
初始化操作
*/
func startScrollForInit()
{
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: #selector(startScroll), userInfo: nil, repeats: true);
}
/**
設定初始滾動位置并開啟定時任務
*/
func startScroll()
{
self.scrollToInit();
//啟動定時器
self.startTime();
}
/**
按鈕點選
- parameter btn: 按鈕
*/
func btnClick(btn:UIButton) -> Void
{
if (btnClick != nil)
{
btnClick!(btn);
}
}
/**
開啟計時器
*/
func startTime() -> Void
{
if timer == nil
{
timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: #selector(scrollForTime), userInfo: nil, repeats: true);
}
}
/**
添加滾動
*/
func scrollForTime() -> Void
{
iCurrentIndex = iCurrentIndex! + 1;
if iCurrentIndex == arrImage!.count + 1
{
imgScrollView!.setContentOffset(CGPointMake(self.bounds.size.width * CGFloat(iCurrentIndex!), 0), animated:true);
iCurrentIndex = 1;
self.performSelector(#selector(scrollToInit), withObject: nil, afterDelay: 0.5);
}
else
{
imgScrollView!.setContentOffset(CGPointMake(self.bounds.size.width * CGFloat(iCurrentIndex!), 0), animated:true);
}
imgPageControl!.currentPage = iCurrentIndex! - 1;
}
/**
回到原點
*/
func scrollToInit() -> Void
{
imgScrollView!.setContentOffset(CGPointMake(self.bounds.size.width * CGFloat(iCurrentIndex!), 0), animated:false);
}
}
最後,通過擴充來遵守UIScrollViewDelegate協定。
extension GofImageScrollView: UIScrollViewDelegate
{
func scrollViewWillBeginDragging(scrollView: UIScrollView)
{
if timer != nil
{
timer!.invalidate();
timer = nil;
}
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView)
{
let index: NSInteger = NSInteger(scrollView.contentOffset.x / kScreenWidth);
if index == (arrImage!.count + 1)
{
scrollView.contentOffset = CGPointMake(self.bounds.size.width, 0);
imgPageControl!.currentPage = 0;
iCurrentIndex = 1;
}
else if index == 0
{
scrollView.contentOffset = CGPointMake(CGFloat(arrImage!.count) * self.bounds.size.width, 0);
imgPageControl!.currentPage = arrImage!.count - 1;
iCurrentIndex = arrImage!.count;
}
else
{
imgPageControl!.currentPage = index - 1;
iCurrentIndex = index;
}
self.startTime();
}
}
2.怎麼用?
//定義圖檔數組
let imageArray: [String] = ["http://tupian.enterdesk.com/2012/1025/gha/1/ebterdesk%20%2810%29.jpg", "http://d.3987.com/qingzang_140909/007.jpg", "http://d.3987.com/mrzr_131022/007.jpg"];
//聲明圖檔輪播視圖
let scroll = GofImageScrollView.gof_ImageScrollView(imageArray, storeType: .Network, btnClickBlock: { (btn) in
printLog("Tag:\(btn.tag)");
}, superView: self.view) { (make) in
make.top.equalTo(0);
make.left.right.equalTo(0);
make.height.equalTo(200);
}
無善無惡心之體,
有善有惡意之動,
知善知惡是良知,
為善去惡是格物。