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

现在很多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下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值