iOS开发系列之常用自定义控件开发集—自动广告墙图片控件开发
2015-04-20 10:17
681 查看
现在很多app都有自动切换图片展示功能尤其是视频播放器,电商app,今天我给大家开发一个这样常用的组件,该控件是纯手工打造,自己实现触摸控制没有用UIScrollView,下面是实现原理:创建三个UIImageView控件通过触摸切换该种方式节省内存,当用户要展示100张图片时也只会创建三个UIImageView控件。
WHC_AdvertisingWall.h 头文件代码如下:
WHC_AdvertisingWall.m源文件实现原理:
运行效果图:
WHC_AdvertisingWallDemo下载
WHC_AdvertisingWall.h 头文件代码如下:
// // WHC_AdvertisingWall.h // WHC_AdvertisingWall // // Created by 吴海超 on 15/3/24. // Copyright (c) 2015年 吴海超. All rights reserved. // #import <UIKit/UIKit.h> @class WHC_AdvertisingWall; //单击图片代理 @protocol WHC_AdvertisingWallDelegate <NSObject> @optional - (void)WHC_AdvertisingWall:(WHC_AdvertisingWall*)whc_AdWallView clickImage:(UIImage*)image index:(NSInteger)index; @end @interface WHC_AdvertisingWall : UIView @property (nonatomic,assign) BOOL isCanTouchScroll; @property (nonatomic,assign) BOOL isCanAutoScroll; @property (nonatomic,assign) id<WHC_AdvertisingWallDelegate> delegate; //以图片对象数组进行初始化 - (instancetype)initWithFrame:(CGRect)frame withImages:(NSArray*)imageArr; - //以图片名称数组进行初始化 - (instancetype)initWithFrame:(CGRect)frame withImageNames:(NSArray *)imageNames; - //以图片对象重载图片 - (void)reloadImage:(NSArray*)images; - //以图片名称重载图片 - (void)reloadImageNames:(NSArray*)imageNames; @end
WHC_AdvertisingWall.m源文件实现原理:
// // WHC_AdvertisingWall.m // WHC_AdvertisingWall // // Created by 吴海超 on 15/3/24. // Copyright (c) 2015年 吴海超. All rights reserved. // #import "WHC_AdvertisingWall.h" #define KWHC_MOVE_IMAGE_DURING (0.4) //动画切换图片周期 #define KWHC_LEFT_START_INDEX (1) //向左切换时的初始imageView下标 #define KWHC_RIGHT_START_INDEX (0) //向右切换时的初始imageView下标 #define KWHC_PAGE_CONTROL_HEIGHT (20.0) //页控件高度 //方向枚举 typedef enum { NONE, LEFT, RIGHT }WHC_TOUCH_ORI; @interface WHC_AdvertisingWall (){ NSArray * _imageArr; //图片数组 NSMutableArray * _imageViewArr; //图片控件数组 UIPageControl * _pageCtl; //页控件 NSTimer * _timer; //定时器 UIPanGestureRecognizer * _panGesture; //触摸手势 CGRect _frame; //该控件frame NSInteger _currentIndex; //当前图片下标 CGPoint _startPoint; //触摸开始点 WHC_TOUCH_ORI _currentMoveOri; //当前移动方向 BOOL _isStartTouch; //是否开始触摸了 } @end @implementation WHC_AdvertisingWall #pragma mark - init - (instancetype)initWithFrame:(CGRect)frame withImages:(NSArray*)imageArr{ self = [super initWithFrame:frame]; if(self != nil){ _currentIndex = 0; _currentMoveOri = NONE; _frame = frame; _imageArr = [NSArray arrayWithArray:imageArr]; _imageViewArr = [NSMutableArray array]; //注册触摸事件 [self registerTouchEvent]; //初始化ui布局 [self initLayout]; } return self; } - (instancetype)initWithFrame:(CGRect)frame withImageNames:(NSArray *)imageNames{ NSMutableArray * images = [NSMutableArray array]; for (NSString * imagePath in imageNames) { [images addObject:[UIImage imageNamed:imagePath]]; } return [self initWithFrame:frame withImages:images]; } #pragma mark - controlAnimation //设置是否可以触摸切换 - (void)setIsCanTouchScroll:(BOOL)isCanTouchScroll{ _isCanTouchScroll = isCanTouchScroll; if(!isCanTouchScroll){ [self removeGestureRecognizer:_panGesture]; }else{ [self addGestureRecognizer:_panGesture]; } } //设置是否可以自动切换 - (void)setIsCanAutoScroll:(BOOL)isCanAutoScroll{ _isCanAutoScroll = isCanAutoScroll; if(isCanAutoScroll){ if(_timer != nil){ [_timer invalidate]; _timer = nil; } _timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(startAutoScrollImage) userInfo:nil repeats:YES]; }else{ [_timer invalidate]; _timer = nil; } } //开始自动切换 - (void)startAutoScrollImage{ //default to left scroll image [self animationMoveImage:KWHC_LEFT_START_INDEX withOri:LEFT]; } #pragma mark - other //加载错误提示view - (void)loadAlertText{ UILabel * labText = [[UILabel alloc]initWithFrame:CGRectMake(0.0, .0, CGRectGetWidth(_frame), CGRectGetHeight(_frame))]; labText.backgroundColor = [UIColor clearColor]; labText.textColor = [UIColor grayColor]; labText.textAlignment = NSTextAlignmentCenter; labText.numberOfLines = 0; labText.text = @"WHC_AdvertisingWall\nimage count = 0"; [self addSubview:labText]; } - (void)registerTouchEvent{ _panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)]; } #pragma mark - reload //重新载入图片(image对象) - (void)reloadImage:(NSArray*)images{ for (UIView * view in self.subviews) { [view removeFromSuperview]; } self.isCanTouchScroll = NO; self.isCanAutoScroll = NO; _currentIndex = 0; _currentMoveOri = NONE; [_imageViewArr removeAllObjects]; _imageArr = nil; _imageArr = [NSArray arrayWithArray:images]; [self initLayout]; } //重新载入图片(image name对象) - (void)reloadImageNames:(NSArray*)imageNames{ NSMutableArray * images = [NSMutableArray array]; for (NSString * imagePath in imageNames) { [images addObject:[UIImage imageNamed:imagePath]]; } [self reloadImage:images]; } #pragma mark - initUI - (void)initLayout{ NSInteger imageCount = _imageArr.count; if(imageCount < 1){ [self loadAlertText]; return; } for (int i = 0; i < 3; i++) { UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake((i - 1) * CGRectGetWidth(_frame), 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame))]; imageView.tag = i; if(i == 1){ imageView.image = _imageArr[0]; }else if(i == 0){ imageView.image = _imageArr[imageCount - 1]; }else{ NSInteger index = i >= imageCount ? imageCount - 1 : i - 1; imageView.image = _imageArr[index]; } [self addSubview:imageView]; [_imageViewArr addObject:imageView]; } _pageCtl = [[UIPageControl alloc]initWithFrame:CGRectMake(0.0, CGRectGetHeight(_frame) - KWHC_PAGE_CONTROL_HEIGHT, CGRectGetWidth(_frame), KWHC_PAGE_CONTROL_HEIGHT)]; _pageCtl.backgroundColor = [UIColor clearColor]; _pageCtl.numberOfPages = imageCount; [self addSubview:_pageCtl]; UIButton * clearBtn = [UIButton buttonWithType:UIButtonTypeCustom]; clearBtn.frame = CGRectMake(.0, .0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)); clearBtn.backgroundColor = [UIColor clearColor]; [clearBtn addTarget:self action:@selector(clickClearBtn:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:clearBtn]; if(imageCount > 1){ self.isCanTouchScroll = YES; self.isCanAutoScroll = YES; } } #pragma mark - handleAnimation //手势触摸移动图片 - (void)touchMoveImage:(NSInteger)index withDistance:(CGFloat)moveXDistace{ for (NSInteger i = index; i < index + 2 ; i++) { //移动图片 CGPoint currImageViewCenter = ((UIImageView *)_imageViewArr[i]).center; ((UIImageView *)_imageViewArr[i]).center = CGPointMake(currImageViewCenter.x + moveXDistace, currImageViewCenter.y); } } //动画切换图片 - (void)animationMoveImage:(NSInteger)index withOri:(WHC_TOUCH_ORI)touchOri{ self.isCanTouchScroll = NO; [UIView animateWithDuration:KWHC_MOVE_IMAGE_DURING animations:^{ //移动图片 for (NSInteger i = index; i < index + 2; i++) { UIImageView * imageView = (UIImageView *)_imageViewArr[i]; CGFloat distanceX = CGRectGetWidth(_frame) / 2.0; if(touchOri == LEFT){ distanceX = -distanceX; imageView.center = CGPointMake((i - 1) * CGRectGetWidth(_frame) + distanceX , imageView.center.y); }else{ imageView.center = CGPointMake(i * CGRectGetWidth(_frame) + distanceX , imageView.center.y); } } } completion:^(BOOL finished) { //动态交换图片控件数组位子 if(touchOri == LEFT){ _currentIndex++; if(_currentIndex >= _imageArr.count){ _currentIndex = 0; } [_imageViewArr exchangeObjectAtIndex:0 withObjectAtIndex:1]; [_imageViewArr exchangeObjectAtIndex:1 withObjectAtIndex:2]; }else{ _currentIndex--; if(_currentIndex < 0){ _currentIndex = _imageArr.count - 1; } [_imageViewArr exchangeObjectAtIndex:0 withObjectAtIndex:2]; [_imageViewArr exchangeObjectAtIndex:1 withObjectAtIndex:2]; } //设置页控件当前页 _pageCtl.currentPage = _currentIndex; for(int i = 0; i < _imageViewArr.count; i++){ //刷新切换后新或者旧图片显示 UIImageView * imageView = _imageViewArr[i]; imageView.center = CGPointMake( i * CGRectGetWidth(_frame) - CGRectGetWidth(_frame) / 2.0, imageView.center.y); if(i == 0){ NSInteger index = _currentIndex - 1; if(index < 0){ index = _imageArr.count - 1; } imageView.image = _imageArr[index]; }else if(i == 1){ imageView.image = _imageArr[_currentIndex]; }else{ NSInteger index = _currentIndex + 1; if(index >= _imageArr.count){ index = 0; } imageView.image = _imageArr[index]; } } self.isCanTouchScroll = YES; }]; } //动画恢复切换状态(手势移动距离不满足条件需要恢复初始状态) - (void)animationResetImage:(NSInteger)index withOri:(WHC_TOUCH_ORI)touchOri{ if(touchOri == LEFT){ index = 1; //向左恢复初始下标 }else{ index = 0; //向右恢复初始下标 } [UIView animateWithDuration:KWHC_MOVE_IMAGE_DURING animations:^{ for (NSInteger i = index; i < 2 + index; i++) { UIImageView * imageView = (UIImageView *)_imageViewArr[i]; CGFloat distanceX = CGRectGetWidth(_frame) / 2.0; if(touchOri == LEFT){ imageView.center = CGPointMake(distanceX + (i - 1) * distanceX * 2.0, imageView.center.y); }else{ imageView.center = CGPointMake(-distanceX + i * distanceX * 2.0, imageView.center.y); } } }]; } #pragma mark - handleGesture //触摸手势处理 - (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture{ switch (panGesture.state) { case UIGestureRecognizerStateBegan: if(self.isCanAutoScroll){ _isStartTouch = YES; self.isCanAutoScroll = NO; } _startPoint = [panGesture locationInView:self]; break; case UIGestureRecognizerStateChanged:{ CGPoint currentPoint = [panGesture locationInView:self]; CGFloat moveXInstance = currentPoint.x - _startPoint.x; if([panGesture velocityInView:self].x < 0){ //left if (_currentMoveOri == RIGHT) { [self touchMoveImage:KWHC_RIGHT_START_INDEX withDistance:-fabsf(moveXInstance)]; }else{ _currentMoveOri = LEFT; [self touchMoveImage:KWHC_LEFT_START_INDEX withDistance:-fabsf(moveXInstance)]; } }else{ //right if(_currentMoveOri == LEFT){ [self touchMoveImage:KWHC_LEFT_START_INDEX withDistance:fabsf(moveXInstance)]; }else{ _currentMoveOri = RIGHT; [self touchMoveImage:KWHC_RIGHT_START_INDEX withDistance:fabsf(moveXInstance)]; } } _startPoint = currentPoint; } break; case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateCancelled:{ UIImageView * imageView = _imageViewArr[1]; if(imageView.center.x <= 0){ [self animationMoveImage:KWHC_LEFT_START_INDEX withOri:LEFT]; }else if(imageView.center.x >= CGRectGetWidth(_frame)){ [self animationMoveImage:KWHC_RIGHT_START_INDEX withOri:RIGHT]; }else{ [self animationResetImage:KWHC_RIGHT_START_INDEX withOri:_currentMoveOri]; } _currentMoveOri = NONE; if(_isStartTouch){ self.isCanAutoScroll = YES; } _isStartTouch = NO; } break; default: break; } } #pragma mark - clickAction //单击图片调用 - (void)clickClearBtn:(UIButton*)sender{ if(_currentIndex <= _imageArr.count - 1){ if(_delegate && [_delegate respondsToSelector:@selector(WHC_AdvertisingWall:clickImage:index:)]){ [_delegate WHC_AdvertisingWall:self clickImage:_imageArr[_currentIndex] index:_currentIndex]; } } } @end
运行效果图:
WHC_AdvertisingWallDemo下载
相关文章推荐
- iOS开发系列之常用自定义控件开发集—自动3D广告墙图片控件开发
- iOS开发系列之常用自定义控件开发集—Android的Toast控件开发
- iOS开发系列之常用自定义控件开发集—进度条Loading控件开发
- iOS开发系列之常用自定义控件开发集—自定义数字键盘控件开发
- iOS开发系列之常用自定义控件开发集—自定义对话框(UIAlertView)控件开发
- iOS开发系列之常用自定义控件开发集—自定义UIPickerView控件开发2
- iOS开发系列之常用自定义控件开发集—自定义UIDatePicker控件开发
- iOS开发系列之常用自定义控件开发集—继承UIButton控件代码快速创建按钮开发
- iOS开发系列之常用自定义控件开发集—自定义组按钮控件开发
- iOS开发系列之常用自定义控件开发集—自定义下拉列表按钮控件开发
- iOS开发系列之常用自定义控件开发集—自定义单选按钮或者多选按钮控件开发
- iOS开发系列之常用自定义控件开发集—自定义状态栏消息提示控件开发
- iOS开发系列之常用自定义控件开发集—自定义UITableViewCell侧滑菜单控件开发
- iOS开发系列之常用框架开发集—自定义UINavigationController开发1
- IOS开发UI系列之常用控件 UILabel, UITextField, UIButton, UIImageView等常用属性与方法
- iOS开发:自定义库实现广告图片轮播
- iOS开发系列课程(06) --- 常用控件介绍
- 【Cocoa(mac) Application 开发系列之二】总结一些常用控件以及简单在自定义View上绘制字符串
- 【Cocoa(mac) Application 开发系列之二】总结一些常用控件及自定义View
- ios开发答疑录系列---(一)Android和IOS图片编码之跨平台传递