新增样式
#import <UIKit/UIKit.h>
/** 方向*/
typedef NS_ENUM(NSInteger, ZJImageLoopViewScrollDirection ) {
/** 不 自 动 循 环(即不开启定时器)*/
ZJImageLoopViewScrollDirectionNone = 0,
/** 从 右 往 左 自 动 循 环*/
ZJImageLoopViewScrollDirectionRightToLeft = 1,
/** 从 左 往 右 自 动 循 环*/
ZJImageLoopViewScrollDirectionLeftToRight = 2,
};
/** 样式*/
typedef NS_ENUM(NSInteger, ZJImageLoopViewScrollStyle ) {
/** 默认 平滑*/
ZJImageLoopViewScrollStyleNone = 0,
/** 前后缩放*/
ZJImageLoopViewScrollStyleZoom = 1,
/** 两端缩放*/
ZJImageLoopViewScrollStyleJustifyZoom = 2,
};
@class ZJImageLoopView;
@protocol ZJImageLoopViewDelegate <NSObject>
@optional
/** 点击时当前显示*/
-(void)ZJImageLoopView:(ZJImageLoopView*)view didSelectSubviewAtIndex:(NSInteger)index;
/** 停止时当前显示*/
-(void)ZJImageLoopView:(ZJImageLoopView*)view didEndDeceleratingAtIndex:(NSInteger)index;
@end
NS_ASSUME_NONNULL_BEGIN
@interface ZJImageLoopView : UIView
@property(nonatomic,assign) ZJImageLoopViewScrollDirection scrollDirection;
@property(nonatomic,weak) id <ZJImageLoopViewDelegate> delegate;
- (instancetype)initWithFrame:(CGRect)frame style:(ZJImageLoopViewScrollStyle)style;
- (void)showImagesWithImageStrs:(NSArray<NSString*>*)imageStrs;
- (void)showDefaultCurrentIndex:(NSInteger)currentIndex;
/** 回调方法*/
- (void)didSelectSubviewAtIndex:(void(^)(NSInteger index))block;
- (void)didEndDeceleratingAtIndex:(void(^)(NSInteger index))block;
@end
NS_ASSUME_NONNULL_END
//
// ZJImageLoopView.m
// ZJUMManager
//
// Created by lizhijiang on 2019/10/28.
// Copyright © 2019年 lizhijiang. All rights reserved.
//
#import "ZJImageLoopView.h"
@interface ZJImageLoopView ()<UIScrollViewDelegate>
@property(nonatomic,strong) NSArray <NSString*>* dataArray;
@property(nonatomic,assign) NSInteger currentIndex;
@property(nonatomic,strong) dispatch_source_t timer;;
@property(nonatomic,weak) UIScrollView * scrollview;
@property(nonatomic,weak) UIImageView * leftImgView;
@property(nonatomic,weak) UIImageView * centerImgView;
@property(nonatomic,weak) UIImageView * rightImgView;
@property(nonatomic,assign) CGRect originalleftFrame;
@property(nonatomic,assign) CGRect originalcentertFrame;
@property(nonatomic,assign) CGRect originalrightFrame;
@property(nonatomic,assign) ZJImageLoopViewScrollStyle style;
@property(nonatomic,copy) void(^didSelectSubviewAtIndexBlock)(NSInteger index);
@property(nonatomic,copy) void(^didEndDeceleratingAtIndexBlock)(NSInteger index);
@end
@implementation ZJImageLoopView
- (instancetype)initWithFrame:(CGRect)frame style:(ZJImageLoopViewScrollStyle)style
{
self = [super initWithFrame:frame];
if (self) {
[self setStyle:style];
[self setSubViews];
}
return self;
}
-(void)setSubViews{
CGRect subframe = CGRectMake(0, 0, CGRectGetWidth([self frame]), CGRectGetHeight([self frame]));
UIScrollView * scroll = [[UIScrollView alloc] initWithFrame:subframe];
[scroll setBounces:false];
[scroll setPagingEnabled:true];
[scroll setDelegate:self];
[scroll setShowsVerticalScrollIndicator:false];
[scroll setShowsHorizontalScrollIndicator:false];
[scroll setContentSize:CGSizeMake(CGRectGetWidth([self frame])*3, 0)];
[scroll setContentOffset:CGPointMake(CGRectGetWidth([self frame]), 0)];
[self setScrollview:scroll];
[self addSubview:scroll];
for(int i=0;i<3;i++){
UIImageView * subview01 = [[UIImageView alloc] init];
[subview01 setContentMode:UIViewContentModeScaleAspectFit];
[scroll addSubview:subview01];
if(i==0){[self setLeftImgView:subview01];}
if(i==1){[self setCenterImgView:subview01];}
if(i==2){[self setRightImgView:subview01];}
// self.leftImgView.backgroundColor = UIColor.redColor;
// self.centerImgView.backgroundColor = UIColor.blueColor;
// self.rightImgView.backgroundColor = UIColor.greenColor;
self.leftImgView.backgroundColor = UIColor.whiteColor;
self.centerImgView.backgroundColor = UIColor.whiteColor;
self.rightImgView.backgroundColor = UIColor.whiteColor;
}
[scroll bringSubviewToFront:[self leftImgView]];
[scroll sendSubviewToBack:[self rightImgView]];
[self allocSubViewsOriginalFrameWithStyle:self.style];
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick)];
[self addGestureRecognizer:tap];
}
#pragma mark -
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
@autoreleasepool {
if(self.style == ZJImageLoopViewScrollStyleJustifyZoom){
[self styleJustifyZoomWithScrollView:scrollView];
}else if (self.style == ZJImageLoopViewScrollStyleZoom){
[self styleZoomWithScrollView:scrollView];
}
}
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
[self handleShowImagesAndrecoveryOriginalFrame];
}
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
[self handleShowImagesAndrecoveryOriginalFrame];
}
//开始拖动的时候调用
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self cancelTimer];
}
//结束拖动时调用
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
[self openTimer];
}
#pragma mark - 定时器
-(void)openTimer{
if(self.timer != nil){return;}
NSTimeInterval time = 2.0;
// 获得队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 创建一个定时器(dispatch_source_t本质还是个OC对象)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 何时开始执行第一个任务
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC));
uint64_t interval = (uint64_t)(time * NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);
// 设置回调
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(self.timer, ^{
if([weakSelf scrollDirection] == 2){
CGPoint offset = [[weakSelf scrollview] contentOffset];
offset.x -= CGRectGetWidth([[weakSelf scrollview] frame]);
[[weakSelf scrollview] setContentOffset:offset animated:true];
}else if([weakSelf scrollDirection] == 1){
CGPoint offset = [[weakSelf scrollview] contentOffset];
offset.x += CGRectGetWidth([[weakSelf scrollview] frame]);
[[weakSelf scrollview] setContentOffset:offset animated:true];
}else{
[weakSelf cancelTimer];
}
});
// 启动定时器
dispatch_resume(self.timer);
}
/** 销毁定时器*/
-(void)cancelTimer{
if(self.timer){
dispatch_cancel(self.timer);
self.timer = nil;
}
}
-(void)dealloc{
[self cancelTimer];
}
#pragma mark - 处理索、图片、坐标
-(void)handleShowImagesAndrecoveryOriginalFrame{
// 处理当前索引
[self handleCurrentIndex];
// 处理图片
[self handleScrollImageViewWithNewImage];
// 恢复坐标
[self recoverySubViewsOriginalFrame];
// 回调
if([self didEndDeceleratingAtIndexBlock]){
self.didEndDeceleratingAtIndexBlock([self currentIndex]);
}
if([self delegate] && [[self delegate] respondsToSelector:@selector(ZJImageLoopView:didEndDeceleratingAtIndex:)]){
[[self delegate] ZJImageLoopView:self didEndDeceleratingAtIndex:[self currentIndex]];
}
}
/// 处理当前索引
-(void)handleCurrentIndex{
// 计算索引
CGFloat offetIndex = [[self scrollview] contentOffset].x/CGRectGetWidth([[self scrollview] frame]);
if(offetIndex == 1){return;}
if(offetIndex>1){// 右往左滑+1
[self setCurrentIndex:[self currentIndex]+1];
if([self currentIndex]>=[[self dataArray] count]){
// 确保索引范围
[self setCurrentIndex:0];
}
}else if(offetIndex<1){// 左往右滑-1
[self setCurrentIndex:[self currentIndex]-1];
if([self currentIndex] <= -1){
// 确保索引范围
[self setCurrentIndex:[[self dataArray] count]-1];
}
}
}
/// 处理图片
- (void)handleScrollImageViewWithNewImage{
[self handleLeftImageViewWithIndex:[self currentIndex]-1];
[self handleCenterImageViewWithIndex:[self currentIndex]];
[self handleRightImageViewWithIndex:[self currentIndex]+1];
}
/// 处理左边imgview
-(void)handleLeftImageViewWithIndex:(NSInteger)index{
NSString * string = @"";
if (index < 0) {
string = self.dataArray.lastObject;
}else if (index < self.dataArray.count){
string = [self.dataArray objectAtIndex:index];
}
[self imageView:self.leftImgView imageString:string];
}
/// 处理中间imgview
-(void)handleCenterImageViewWithIndex:(NSInteger)index{
NSString * string = @"";
if (index < self.dataArray.count){
string = [self.dataArray objectAtIndex:index];
}
[self imageView:self.centerImgView imageString:string];
}
/// 处理右边imgview
-(void)handleRightImageViewWithIndex:(NSInteger)index{
NSString * string = @"";
if (index >= self.dataArray.count) {
string = self.dataArray.firstObject;
}else if (index >= 0){
string = [self.dataArray objectAtIndex:index];
}
[self imageView:self.rightImgView imageString:string];
}
/// 加载图片
-(void)imageView:(UIImageView*)imgView imageString:(NSString*)string{
if([string containsString:@"http"]){// 网络图片
}else if([string containsString:@"/"]){// 路径图片
[imgView setImage:[UIImage imageWithContentsOfFile:string]];
}else {// 本地图片名称
[imgView setImage:[UIImage imageNamed:string]];
}
}
#pragma mark - 位置
/// 初始化位置
-(void)allocSubViewsOriginalFrameWithStyle:(ZJImageLoopViewScrollStyle)style{
if(style == ZJImageLoopViewScrollStyleNone){
[self originalFrameWithStyleNone];
}else if(style == ZJImageLoopViewScrollStyleZoom){
[self originalFrameWithStyleZoom];
}else if(style == ZJImageLoopViewScrollStyleJustifyZoom){
[self originalFrameWithStyleJustifyZoom];
}
}
-(void)originalFrameWithStyleNone{
CGFloat width = CGRectGetWidth(self.scrollview.frame);
CGFloat height = CGRectGetHeight(self.scrollview.frame);
self.originalcentertFrame = CGRectMake(width, 0, width, height);
self.centerImgView.frame = self.originalcentertFrame;
self.originalleftFrame = CGRectMake(0, 0, width, height);
self.leftImgView.frame = self.originalleftFrame;
self.originalrightFrame = CGRectMake(width*2, 0, width, height);
self.rightImgView.frame = self.originalrightFrame;
}
-(void)originalFrameWithStyleZoom{
[self originalFrameWithStyleNone];
}
-(void)originalFrameWithStyleJustifyZoom{
CGFloat margin = 30;
CGFloat centerX = CGRectGetWidth(self.scrollview.frame)*1.5;
CGFloat centerY = CGRectGetHeight(self.scrollview.frame)*0.5;
CGFloat width = (CGRectGetWidth(self.scrollview.frame)-margin*2);
CGFloat height = (CGRectGetWidth(self.scrollview.frame)*0.7-40);
self.originalcentertFrame = CGRectMake(centerX-width*0.5, centerY-height*0.5, width, height);
self.centerImgView.frame = self.originalcentertFrame;
height -= 60;
width = self.originalcentertFrame.size.width/self.originalcentertFrame.size.height * height;
centerX = CGRectGetMinX(self.centerImgView.frame) - margin*0.5 - width*0.5;
self.originalleftFrame = CGRectMake(centerX-width*0.5, centerY-height*0.5, width, height);
self.leftImgView.frame = self.originalleftFrame;
centerX = CGRectGetMaxX(self.centerImgView.frame) + margin*0.5 + width*0.5;
self.originalrightFrame = CGRectMake(centerX-width*0.5, centerY-height*0.5, width, height);
self.rightImgView.frame = self.originalrightFrame;
}
/// 恢复初始化位置
-(void)recoverySubViewsOriginalFrame{
self.leftImgView.frame = self.originalleftFrame;
self.centerImgView.frame = self.originalcentertFrame;
self.rightImgView.frame = self.originalrightFrame;
// 保证中心位置
[self.scrollview setContentOffset:CGPointMake(CGRectGetWidth([self.scrollview frame]), 0)];
}
#pragma mark - 点击图片
-(void)tapClick{
if([self delegate] && [[self delegate] respondsToSelector:@selector(ZJImageLoopView:didSelectSubviewAtIndex:)]){
[[self delegate] ZJImageLoopView:self didSelectSubviewAtIndex:[self currentIndex]];
}
if([self didSelectSubviewAtIndexBlock]){
self.didSelectSubviewAtIndexBlock([self currentIndex]);
}
}
#pragma mark - 外界方法
- (void)showImagesWithImageStrs:(NSArray<NSString*>*)imageStrs{
if(imageStrs.count<1){return;}
[self setDataArray:imageStrs];
[self setCurrentIndex:0];
// 处理图片
[self handleScrollImageViewWithNewImage];
///
[self showDefaultCurrentIndex:[self currentIndex]];
if([self scrollDirection] && [self scrollDirection] != 0){
[self openTimer];
}else{
[self cancelTimer];
}
}
- (void)showDefaultCurrentIndex:(NSInteger)currentIndex{
[self setCurrentIndex:currentIndex];
[self handleScrollImageViewWithNewImage];
}
- (void)didSelectSubviewAtIndex:(void(^)(NSInteger index))block{
[self setDidSelectSubviewAtIndexBlock:block];
}
- (void)didEndDeceleratingAtIndex:(void(^)(NSInteger index))block{
[self setDidEndDeceleratingAtIndexBlock:block];
}
#pragma mark - 样式 styleZoom
-(void)styleZoomWithScrollView:(UIScrollView*)scroll{
CGFloat offset = scroll.contentOffset.x;
CGSize size = self.frame.size;
CGFloat scale = 0.6;
if(offset>CGRectGetWidth([self frame])){// 从右往左
CGRect subFrame = CGRectMake(0, 0, size.width*scale, 0);
CGPoint center = CGPointMake(size.width*0.5+offset, size.height*0.5);
subFrame.size.width += (offset-size.width*1.0)*(1-scale);
subFrame.size.height = size.height*subFrame.size.width/size.width;
[[self rightImgView] setFrame:subFrame];
[[self rightImgView] setCenter:center];
[[self leftImgView] setCenter:CGPointMake(size.width*0.5, size.height*0.5)];
}else{// 从左往右
CGRect subFrame = CGRectMake(0, 0, size.width, size.height);
CGPoint center = CGPointMake(size.width*0.5+offset, size.height*0.5);
subFrame.size.width -= (size.width-offset)*(1-scale);
subFrame.size.height = size.height*subFrame.size.width/size.width;
[[self centerImgView] setFrame:subFrame];
[[self centerImgView] setCenter:center];
[[self rightImgView] setCenter:CGPointMake(size.width*2.5, size.height*0.5)];
}
}
#pragma mark - 样式 styleJustifyZoom
-(void)styleJustifyZoomWithScrollView:(UIScrollView*)scroll{
CGFloat offset = scroll.frame.size.width - scroll.contentOffset.x;
if(offset>0) {// 从左往右
[self JustifyZoomLeftToRightWithChangeValue:offset];
}else{
[self JustifyZoomRightToLeftWithChangeValue:offset];
}
}
/// styleZoom从左往右
-(void)JustifyZoomLeftToRightWithChangeValue:(CGFloat)offset{
self.leftImgView.frame = [self JustifyZoomEnlargeWithOriginalFrame:self.originalleftFrame changeValue:offset];
self.centerImgView.frame = [self JustifyZoomNarrowWithOriginalFrame:self.originalcentertFrame changeValue:offset];
}
/// styleJustifyZoom从右往左
-(void)JustifyZoomRightToLeftWithChangeValue:(CGFloat)offset{
self.rightImgView.frame = [self JustifyZoomEnlargeWithOriginalFrame:self.originalrightFrame changeValue:-offset];
self.centerImgView.frame = [self JustifyZoomNarrowWithOriginalFrame:self.originalcentertFrame changeValue:-offset];
}
/// 放大坐标
-(CGRect)JustifyZoomEnlargeWithOriginalFrame:(CGRect)frame changeValue:(CGFloat)value{
CGFloat max = self.originalcentertFrame.size.height;
CGFloat centerX = frame.origin.x+frame.size.width*0.5;
CGFloat centerY = frame.origin.y+frame.size.height*0.5;
CGFloat H = (frame.size.height + value) > max ? max : (frame.size.height + value);
CGFloat W = frame.size.width/frame.size.height * H;
CGRect newFrame = CGRectMake(centerX-W*0.5, centerY-H*0.5, W, H);
return newFrame;
}
/// 缩小坐标
-(CGRect)JustifyZoomNarrowWithOriginalFrame:(CGRect)frame changeValue:(CGFloat)value{
CGFloat min = self.originalleftFrame.size.height;
CGFloat centerX = frame.origin.x+frame.size.width*0.5;
CGFloat centerY = frame.origin.y+frame.size.height*0.5;
CGFloat H = (frame.size.height - value) < min ? min : (frame.size.height - value);
CGFloat W = frame.size.width/frame.size.height * H;
CGRect newFrame = CGRectMake(centerX-W*0.5, centerY-H*0.5, W, H);
return newFrame;
}
@end