您的位置:首页 > 移动开发 > IOS开发

iOS开发系列之常用自定义控件开发集—自动广告墙图片控件开发

2015-04-20 10:17 681 查看
现在很多app都有自动切换图片展示功能尤其是视频播放器,电商app,今天我给大家开发一个这样常用的组件,该控件是纯手工打造,自己实现触摸控制没有用UIScrollView,下面是实现原理:创建三个UIImageView控件通过触摸切换该种方式节省内存,当用户要展示100张图片时也只会创建三个UIImageView控件。

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下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐