子控件悬停及scrollView细节

UIScrollView、控件悬停、顶部图下拉放大效果、UITouch事件

UIScrollView的基本属性

  • 超出UIScrollView边框的内容会被自动隐藏
  • contentSize
    • 设置scrollView的contentSize属性,告诉UIScrollView所有内容的尺寸,也就是告诉它滚动范围(最多能滚多远)
    • UIScrollView无法滚动的可能原因
      • 没有设置contentSize
      • scrollEnabled = NO;
      • 禁止了触摸事件:userInteractionEnabled = NO
    • 如果想要禁止某个方向的滚动,那么就可以直接设置这个方向的contentSize为0
      eg:

// 禁止水平方向上滚动
self.scrollView.contentSize = CGSizeMake(0, 500);
contentOffset:(偏移量)

  • 记录UIScrollView滚动的位置,也就是内容的左上角和scrollView自身左上角X\Y的差值
    • 对于X\Y值,如果内容往左上方滚动,X\Y都是增加,如果内容往右下方滚动,X\Y都是减少
      eg:

// 往下移动64
self.scrollView.contentOffset = CGPointMake(0, -64);

OC语法细节:OC不允许直接修改结构体对象的属性成员变量

contentInset:内边距

  • 这个属性能够在UIScrollView的四周增加额外的滚动区域,一般用来避免scrollView的内容被其他控件挡住(比如不被导航条挡住)
    eg:

// 顶部多出64的内边距
self.scrollView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
UIScrollView的其他属性

  • BOOL bounces
    • 设置UIScrollView是否需要弹簧效果
  • BOOL scrollEnabled
    • 设置UIScrollView是否能滚动
  • BOOL showHorizontalScrollIndicator
    • 是否显示水平滚动条
  • BOOL showsVerticalScrollIndicator
    • 是否显示垂直滚动条
  • BOOL pagingEnabled
    • 是否分页
      注意

iOS7以后,导航控制器会为其中的scrollView的顶部自动添加64的内边距,如果想去掉,可以通过下列属性去掉
tabBarController为间隔区域的bottom添加49
取消自动添加额外滚动区域

self.automaticallyAdjustsScrollViewInsets = NO;
UIScrollView的代理方法

使用方法

首先准守协议
设置代理
实现代理方法
注意
如果其他类(A类)成为该类中UIScrollView的代理的话,需要将 A类设成Strong,然后它成为当前类中scrollView的代理
常用代理方法为

/**
 *  滚动的时候调用
 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{

}

/**
 *  即将开始拖拽的时候调用
 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{

}

/**
 *  结束拖拽的时候调用
 */
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{

}

/**
 *  (减速完毕)停止滚动的时候调用
 */
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{

}
scrollView实现内容缩放
// 最大缩放比例
self.scrollView.maximumZoomScale = 2.0;
// 最小缩放比例
self.scrollView.minimumZoomScale = 0.2;

// 同时实现代理方法
// 返回要缩放的内容控件,注意,该内容控件必须是scrollView的子控件
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

// 这个方式是内容缩放的时候调用,通过在该方法中调节内容控件的frame可以使缩放的时候内容控件始终处于scrollView的正中间
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{

}

其他方法
// 将scrollView中的所有子控件都执行removeFromSuperview方法
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
ScrollView内部子控件添加约束的注意点

子控件的尺寸不能通过UIScrollView来计算,可以考虑通过以下方式计算

可以设置尺寸为固定值
可以相对于UIScrollView以外的其他控件来计算尺寸
UIScrollView的frame应该通过子控件以外的其他控件来计算

UIScrollView的contentSize的尺寸是通过子控件来计算的
根据子控件的尺寸以及子控件与UIScrollView之间的间距
ScrollView的一些特效效果

控件悬停效果

当scrollView往上拖拽到某一个位置的时候,控件(testView)悬停到某一个位置,当scrollView往下拉的时候,该控件(testView)又随着scrollView一起移动
实现思路:

当往上拖拽到一定位置的时候(通过计算偏移量来判断),让该控件(testView)添加到self.view上,并设置该控件(testView)的frame固定到该位置,当scrollView再次往回拖拽到该位置的时候,再让该控件(testView)再添加到scrollView上,成为scrollView的子控件

顶部图片下拉放大效果

当scrollView往下拖拽的时候,让顶部的imageView按比例放大
实现思路:

当scrollView往下拖拽的时候,通过偏移量来修改顶部imageView的transform(缩放的transform)。

eg:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat imageH = self.imageView.frame.size.height;
    CGFloat offsetY = scrollView.contentOffset.y;
    // 该判断是实现scrollView内部的子控件悬停效果
    if (offsetY >= imageH) {
        // 将红色控件添加到控制器的view中,设置Y值为0
        CGRect redF = self.redView.frame;
        redF.origin.y = 0;
        self.redView.frame = redF;
        [self.view addSubview:self.redView];
    }else{
        // 将红色控件添加到scrollView中,设置Y值为图片的高度
        CGRect redF = self.redView.frame;
        redF.origin.y = 140;
        self.redView.frame = redF;
        [self.scrollView addSubview:self.redView];
    }

    // 实现下拉放大顶部图片效果
    CGFloat scale = 1 - (offsetY / 70);
    scale = (scale >= 1) ? scale : 1;
    self.imageView.transform = CGAffineTransformMakeScale(scale, scale);
}

分页指示器UIPageControl

UIPageControl
颜色指示器
tintColor: 其他页面的指示颜色
currentPageIndicatorTintColor:当前页颜色
numberOfPages:总共有多少页
注意 一定不要将UIPageControl放到UIScrollView里,这样的话UIScrollView的内容拖动的时候容易把UIPageControl拖走

pageControl.hidesForSinglePage = YES;
当只有一页时自动隐藏pageControl
关于UIScrollView不能响应UITouch事件的解决办法

原因是:UIView的touch事件被UIScrollView捕获了。

解决办法:让UIScrollView将事件传递过去。于是最简单的解决办法就是加一个UIScrollView的category。这样每个用到UIScrollView的地方只要导入这个category就可以直接响应相关的touch事件了。

#import "UIScrollView+UITouch.h"

@implementation UIScrollView (UITouch)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  [[self nextResponder] touchesBegan:touches withEvent:event];
  [super touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  [[self nextResponder] touchesMoved:touches withEvent:event];
  [super touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  [[self nextResponder] touchesEnded:touches withEvent:event];
  [super touchesEnded:touches withEvent:event];
}

@end

你可能感兴趣的:(子控件悬停及scrollView细节)