IOS中无限滚动Scrollview效果

本文实例讲了IOS无限滚动效果,分享给大家供大家参考,具体内容如下

滑动到当前位置时候才去请求,本地有内容则直接显示(以来SDWebImage,UIView+Ext)
HZScrollView.h

#import <UIKit/UIKit.h>

typedef void(^HZReturnBlock)(NSInteger index,CGFloat offset);

typedef NS_ENUM(NSUInteger, HZScrollViewPageControllPosition) {
  HZScrollViewPageControllPositionNone,
  HZScrollViewPageControllPositionLeft,
  HZScrollViewPageControllPositionCenter,
  HZScrollViewPageControllPositionRight,
};

@class HZScrollView;
@protocol HZScrollViewDelegate <NSObject>

@optional
- (void)resetPosition:(HZScrollView *)scrollView AndIndex:(NSInteger)index;

@end

@interface HZScrollView : UIView
/**
 * 返回当前位置
 */
@property (nonatomic, weak)id <HZScrollViewDelegate>delegate;
/**
 * 默认图
 */
@property (nonatomic, strong) UIImage *hz_placeImage;
/**
 * 图片列表哇
 */
@property (nonatomic, strong) NSArray *hz_ImageList;
/**
 * pagecongroll 位置
 */
@property (nonatomic, assign) HZScrollViewPageControllPosition hz_PageControllPosition;
/**
 * 变换自身frame
 *
 * @param offset 偏移量
 */
- (void)transformView:(CGFloat)offset;
/**
 * 获取当前位置以及便宜
 *
 * @param block 返回内容
 */
- (void)hz_getContent:(HZReturnBlock)block;

@end

HZScrollView.m

#import "UIImageView+WebCache.h"
#import "HZScrollView.h"
#import "UIView+DylanFramTool.h"
#define HZ_FormatImage(val_imageView)\
- (UIImageView *)val_imageView\
{\
if (!_##val_imageView) {\
_##val_imageView = [[UIImageView alloc] init];\
}\
return _##val_imageView;\
}\

//宽度
#define HZ_SWidth  self.bounds.size.width
//高度
#define HZ_SHeight  self.bounds.size.height

#define HZ_PHeight  16

@interface HZScrollView ()<UIScrollViewDelegate>

@property (nonatomic, copy) HZReturnBlock hz_block;
/**
 * 总数
 */
@property (nonatomic,assign) NSInteger hz_MaxCount;
/**
 * 当前位置
 */
@property (nonatomic,assign) NSInteger hz_currentIndex;
/**
 * 容器
 */
@property (nonatomic, strong) UIScrollView *scrollView;
/**
 * 你懂滴
 */
@property (nonatomic, strong) UIPageControl *pageControll;

/**视图**/
@property (nonatomic, strong) UIImageView *leftImageView;
@property (nonatomic, strong) UIImageView *centerImageView;
@property (nonatomic, strong) UIImageView *rightImageView;

@end

@implementation HZScrollView
{
  CGRect _hz_Frame;
}

#pragma mark -
#pragma mark - init
- (instancetype)initWithFrame:(CGRect)frame
{
  self = [super initWithFrame:frame];
  if (self) {
    _hz_Frame = frame;
    [self addSubview:self.scrollView];
    [self configImageView];
    [self addSubview:self.pageControll];
  }
  return self;
}
#pragma mark -
#pragma mark - config
- (void)configImageView
{
  self.leftImageView.frame = CGRectMake(0, 0, HZ_SWidth, HZ_SHeight);
  [self.scrollView addSubview:self.leftImageView];
  self.centerImageView.frame = CGRectMake(HZ_SWidth, 0, HZ_SWidth, HZ_SHeight);
  [self.scrollView addSubview:self.centerImageView];
  self.rightImageView.frame = CGRectMake(HZ_SWidth * 2, 0, HZ_SWidth, HZ_SHeight);
  [self.scrollView addSubview:self.rightImageView];
}
#pragma mark -
#pragma mark - reSet
- (void)setHz_placeImage:(UIImage *)hz_placeImage
{
  _hz_placeImage = hz_placeImage;
  [self changeImageLeft:-1 center:-1 right:-1];
  if (self.hz_MaxCount) {
    [self setHz_MaxCount:self.hz_ImageList.count];
  }
}
- (void)setHz_ImageList:(NSArray *)hz_ImageList
{
  _hz_ImageList = [hz_ImageList copy];
  [self setHz_MaxCount:_hz_ImageList.count];
}
- (void)setHz_MaxCount:(NSInteger)hz_MaxCount
{
  _hz_MaxCount = hz_MaxCount;

  switch (_hz_MaxCount) {
    case 0:
      self.scrollView.scrollEnabled = NO;
      [self changeImageLeft:-1 center:-1 right:-1];
      break;
    case 1:
      self.scrollView.scrollEnabled = NO;
      [self changeImageLeft:0 center:0 right:0];
      break;

    default:
      self.scrollView.scrollEnabled = YES;
      [self changeImageLeft:_hz_MaxCount - 1 center:0 right:1];
      break;
  }

  self.pageControll.numberOfPages = _hz_MaxCount;
  [self setHz_PageControllPosition:_hz_PageControllPosition];
}
- (void)setHz_PageControllPosition:(HZScrollViewPageControllPosition)hz_PageControllPosition
{
  _hz_PageControllPosition = hz_PageControllPosition;
  CGFloat width = self.hz_MaxCount * HZ_PHeight;
  switch (_hz_PageControllPosition) {
    case HZScrollViewPageControllPositionNone:
      self.pageControll.hidden = YES;
      break;
    case HZScrollViewPageControllPositionLeft:
      self.pageControll.hidden = NO;
      self.pageControll.frame = CGRectMake(10, self.pageControll.frame.origin.y, width, self.pageControll.frame.size.height);
      break;
    case HZScrollViewPageControllPositionCenter:
      self.pageControll.hidden = NO;
      self.pageControll.frame = CGRectMake((self.bounds.size.width - width)/2.f, self.pageControll.frame.origin.y, width, self.pageControll.frame.size.height);
      break;
    case HZScrollViewPageControllPositionRight:
      self.pageControll.hidden = NO;
      self.pageControll.frame = CGRectMake(self.bounds.size.width - 10 - width, self.pageControll.frame.origin.y, width, self.pageControll.frame.size.height);
      break;
    default:
      break;
  }
  if (width <= HZ_PHeight) {
    self.pageControll.hidden = YES;
  }
}
#pragma mark -
#pragma mark - LZ
- (UIScrollView *)scrollView
{
  if (!_scrollView) {
    _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
    _scrollView.pagingEnabled = YES;
    _scrollView.showsHorizontalScrollIndicator = NO;
    _scrollView.delegate = self;
    _scrollView.contentSize = CGSizeMake(HZ_SWidth * 3,0);
  }
  return _scrollView;
}
- (UIPageControl *)pageControll
{
  if (!_pageControll) {
    _pageControll = [[UIPageControl alloc] initWithFrame:CGRectMake(0,HZ_SHeight - HZ_PHeight,HZ_PHeight, 7)];
    _pageControll.pageIndicatorTintColor = [UIColor lightGrayColor];
    _pageControll.currentPageIndicatorTintColor = [UIColor whiteColor];
    _pageControll.numberOfPages = self.hz_MaxCount;
    _pageControll.currentPage = 0;
  }
  return _pageControll;
}
HZ_FormatImage(leftImageView);
HZ_FormatImage(centerImageView);
HZ_FormatImage(rightImageView);
#pragma mark -
#pragma mark - private Method

- (void)changeImageWithOffset:(CGFloat)offsetX
{

  if (offsetX >= HZ_SWidth * 2) {
    self.hz_currentIndex++;

    if (self.hz_currentIndex == self.hz_MaxCount - 1) {

      [self changeImageLeft:self.hz_currentIndex - 1 center:self.hz_currentIndex right:0];

    }else if (self.hz_currentIndex == self.hz_MaxCount) {

      self.hz_currentIndex = 0;
      [self changeImageLeft:self.hz_MaxCount - 1 center:0 right:1];

    }else {
      [self changeImageLeft:self.hz_currentIndex-1 center:self.hz_currentIndex right:self.hz_currentIndex + 1];
    }
    if (self.hz_block) {
      self.hz_block(self.hz_currentIndex,offsetX);
    }
    self.pageControll.currentPage = self.hz_currentIndex;

  }

  if (offsetX <= 0) {
    self.hz_currentIndex--;

    if (self.hz_currentIndex == 0) {

      [self changeImageLeft:self.hz_MaxCount-1 center:0 right:1];

    }else if (self.hz_currentIndex == -1) {

      self.hz_currentIndex = self.hz_MaxCount-1;
      [self changeImageLeft:self.hz_currentIndex-1 center:self.hz_currentIndex right:0];

    }else {
      [self changeImageLeft:self.hz_currentIndex-1 center:self.hz_currentIndex right:self.hz_currentIndex+1];
    }
    if (self.hz_block) {
      self.hz_block(self.hz_currentIndex,offsetX);
    }
    self.pageControll.currentPage = self.hz_currentIndex;
  }
  [self setHz_PageControllPosition:_hz_PageControllPosition];

}

- (void)changeImageLeft:(NSInteger)leftIndex center:(NSInteger)centerIndex right:(NSInteger)rightIndex
{
  if (self.hz_currentIndex > self.hz_MaxCount) {
    return;
  }
  if (leftIndex == -1 && centerIndex == -1 && rightIndex == -1) {
    self.leftImageView.image = self.hz_placeImage;
    self.centerImageView.image = self.hz_placeImage;
    self.rightImageView.image = self.hz_placeImage;
  } else {
    [self checkExistImage:self.hz_ImageList[leftIndex]
          ImageView:self.leftImageView
         CurrentIndex:@(leftIndex)];
    [self checkExistImage:self.hz_ImageList[centerIndex]
          ImageView:self.centerImageView
         CurrentIndex:@(centerIndex)] ;
    [self checkExistImage:self.hz_ImageList[rightIndex]
          ImageView:self.rightImageView
         CurrentIndex:@(rightIndex)];
  }
  [self.scrollView setContentOffset:CGPointMake(HZ_SWidth, 0)];

}

- (void)checkExistImage:(NSString *)urlString
       ImageView:(UIImageView *)currentImageView
      CurrentIndex:(NSNumber *)index
{
  if ([[[SDWebImageManager sharedManager] imageCache] imageFromDiskCacheForKey:urlString])
  {
    currentImageView.image = [[[SDWebImageManager sharedManager] imageCache] imageFromMemoryCacheForKey:urlString];
    return;
  } else {
    currentImageView.image = self.hz_placeImage;
    if (self.hz_currentIndex != [index integerValue]) {
      return;
    }
    [self performSelector:@selector(downLoadImage:) withObject:@[urlString,currentImageView] afterDelay:0 inModes:@[NSDefaultRunLoopMode]];
  }

}
- (void)downLoadImage:(NSArray *)param
{
  NSString *urlString = [param firstObject];
  __weak UIImageView *currentImageView = [param lastObject];
  [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:urlString] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
    NSLog(@"received:%@",@(receivedSize));
  } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
    currentImageView.image = image;
//    [[[SDWebImageManager sharedManager] imageCache] storeImage:image forKey:urlString];
    [[[SDWebImageManager sharedManager] imageCache] storeImage:image forKey:urlString toDisk:YES];
  }];
}
#pragma mark -
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
  [self changeImageWithOffset:scrollView.contentOffset.x];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  NSInteger index = scrollView.contentOffset.x/scrollView.width;

  if ([self.delegate respondsToSelector:@selector(resetPosition:AndIndex:)]) {
    [self.delegate resetPosition:self AndIndex:self.hz_currentIndex];
  }
}
#pragma mark -
#pragma mark - public method
- (void)transformView:(CGFloat)offset
{
  if (offset > 0) {
    return;
  }
  CGFloat currentHeight = 210 - offset;
  self.height = currentHeight ;
  CGFloat currentScale = currentHeight / _hz_Frame.size.height;
  self.left = _hz_Frame.origin.x - (_hz_Frame.size.width * currentScale - _hz_Frame.size.width)/2.f;
  self.width = _hz_Frame.size.width * currentScale;
  self.top = offset;

  self.scrollView.size = self.size;

  self.leftImageView.size = self.size;
  self.centerImageView.size = self.size;
  self.rightImageView.size = self.size;

  self.centerImageView.x = self.width;

  self.rightImageView.x = self.width * 2;

  self.scrollView.contentSize = CGSizeMake(self.width *3, self.height);
  [self.scrollView setContentOffset:CGPointMake(HZ_SWidth, 0)];
}

- (void)hz_getContent:(HZReturnBlock)block
{
  self.hz_block = block;
}
- (void)layoutSubviews
{
  [super layoutSubviews];

}

@end

以上就是本文的全部内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • iOS scrollview实现三屏复用循环广告

    循环广告我们在开发中已经是熟得不能再熟了,今天整理这篇scrollview三屏复用广告. 原理使用scrollview里的三个imageview分别去加载不同的图片,用少量的资源来显示大量或不确定的广告数量,不然如果用普通方法实现广告,难道10个广告用12个scrollview的contentsize去做,岂不是太浪费资源了 代码如下,实现所有数量的循环广告,当广告只有一个时,仅采用单图显示,>=2个广告时,自动采用三屏复用 这里添加图片的方式是通过网络请求,更新服务器上的广告,如果仅使用本地广

  • iOS实现scrollview上拉显示Navbar下拉隐藏功能详解

    本文主要介绍的是关于iOS中scrollview上拉显示Navbar下拉隐藏的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 动画效果: 关于下拉隐藏Nabbar,上拉显示,有三种方式:推崇第一种,但是做的还是没简书.知乎那样流畅,第一种是对navbar做了平移,第二种,第三种都是隐藏.. 方法如下: 第一种,和第二种处理时机一样,但是效果更好,并没有处理Navbar 的隐藏. -(void)scrollViewWillBeginDragging:(UIScrollView *)scr

  • IOS中无限滚动Scrollview效果

    本文实例讲了IOS无限滚动效果,分享给大家供大家参考,具体内容如下 滑动到当前位置时候才去请求,本地有内容则直接显示(以来SDWebImage,UIView+Ext) HZScrollView.h #import <UIKit/UIKit.h> typedef void(^HZReturnBlock)(NSInteger index,CGFloat offset); typedef NS_ENUM(NSUInteger, HZScrollViewPageControllPosition) {

  • iOS中无限循环滚动简单处理实现原理分析

    说下原理: 1./*初始化/ + (instancetype)loopScrollViewWithFrame:(CGRect)frame; 将背景collectinview视图初始化设置 代理和数据源 . 布局 2.在激活initwithFrame后触发 layoutSubviews //默认滚动到要显示的第一张图片 if (self.imageCollectionView.contentOffset.x == 0) { NSIndexPath *indexPath = [NSIndexPath

  • iOS中Navbar设置渐变色效果的方法示例

    本文主要给大家介绍了关于iOS中Navbar设置渐变色效果的相关内容,分享出来供大家参考学习,下面来看看详细的介绍吧. 设置渐变色 #import "NavigationViewController.h" #define LBColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] @interface NavigationViewController () @end

  • IOS中UITableView滚动到指定位置

    方法很简单: - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated 有些需要注意的地方: 如果在reloadData后需要立即获取tableview的cell.高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是有可能出问题的. reloadDa

  • Android UI设计系列之自定义SwitchButton开关实现类似IOS中UISwitch的动画效果(2)

    做IOS开发的都知道,IOS提供了一个具有动态开关效果的UISwitch组件,这个组件很好用效果相对来说也很绚丽,当我们去点击开关的时候有动画效果,但遗憾的是Android上并没有给我们提供类似的组件(听说在Android4.0的版本上提供了具有动态效果的开关组件,不过我还没有去看文档),如果我们想实现类似的效果那该怎么办了呢?看来又得去自定义了. 公司的产品最近一直在做升级,主要做的就是把界面做的更绚丽更美观给用户更好的体验(唉,顾客是上帝......),其中的设置功能中就有开关按钮,原来的开

  • IOS中MMDrawerController第三方抽屉效果的基本使用示例

    因为刚开年,所以最近公司比较闲,看到以前并不是我接手的项目中有这种抽屉效果的控制器,比较感兴趣,便对MMDrawerController研究起来.也方便自己忘记之后查阅,另外也希望对大家有所帮助(PS:以前都是上面一个导航栏,下面一个tabbar的项目居多,所以对这种抽屉控制器不是很了解). 1.首先,到GitHub上把MMDrawerController下下来,然后倒入到项目中.当然你用cocoapods倒入也行.看你心情呗O(∩_∩)O 2.接下来就在appdelegate中撸我们的代码了.

  • UGUI实现ScrollView无限滚动效果

    抽空做了一个UGUI的无限滚动的效果.只做了一半(向下无限滚动).网上也看了很多教程,感觉还是按照自己的思路来写可能比较好.搭建如下: content节点不添加任何组件.布局组件默认是会重新排版子节点的,所以如果子节点的位置变化,会重新排版,不能达到效果.Size Fitter组件也不加,自己写代码调整Size大小(不调整大小,无法滑动). 最主要的实现过程就是用Queue来搬运Cell.在向下滚动的过程中(鼠标上滑),顶部滑出View Port的Cell被搬运到底部续上.这点类似于Queue的

  • 详解无限滚动插件vue-infinite-scroll源码解析

    最近在项目中遇到一个需求,有一个列表需要滚动加载,类似于微博的无限滚动.当时第一反应时监听滚动事件,在判断滚动到达底部时加载下一页,同时心里也清楚,监听滚动事件需要做好截流.顺手搜索了下发现有一个现成的插件vue-infinite-scroll,用法也很简单,于是乎就用了起来. 需求上线后,对它的实现挺好奇的,于是研究了一番源码,这篇文章就是源码解析笔记. 插件使用方法 这是一个 vue 的指令,按照 github 仓库上的介绍,用法挺简单的,例如: <div class="app&quo

  • 基于Vue实现卡片无限滚动动画

    目录 概要设计 详细设计 进阶功能 功能分析 概要设计 详细设计 完整代码 概要设计 设置css的animation在适当的时间点重置动画来现实视觉上无限滚动的效果. 详细设计 计算动画中所需预设的卡片dom节点个数(即视觉上最多能看到的卡片个数),如图1视窗高度为120px,卡片高度为56px,上下margin均为24px,因此一张卡片最多占据56+24*2=104px.当卡片处于视窗垂直居中的位置时,卡片上下各有(120-104)/2 = 8px的高度来承载其余卡片,因此所需预设卡片dom节

  • iOS中给UITableView的侧滑删除增加多个按钮的实现方法

    一. 需求: cell的侧滑删除默认只有一个删除按钮, 给侧滑添加多个按钮, '删除', '置顶', '更多'.  二. 实现说明: 1) 我们在使用一些应用的时候,在滑动一些联系人的某一行的时候,会出现删除.置顶.更多等等的按钮,在iOS8之前,我们都需要自己去实现.但是到了iOS8,系统已经写好了,只需要一个代理方法和一个类就搞定了 2) iOS8的协议多了一个方法,返回值是数组的tableView:editActionsForRowAtIndexPath:方法,我们可以在方法内部写好几个按

随机推荐