理解UIScrollView
理解UIScrollView
人生天地间 发表于3年前
理解UIScrollView
  • 发表于 3年前
  • 阅读 283
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

摘要: 原文来自http://oleb.net/blog/2014/04/understanding-uiscrollview/,你还可以看看原版的!

     Coordinate Systems (系统坐标)

 每个视图都可以定义它自己的坐标。就像下面的图一样:

A standard x/y coordinate system with the x-axis pointing right and the y-axis pointing down

     一个UIView 的系统坐标

注意:这种逻辑坐标和并不在意视图的宽度和高度本身。它没有边界,可以无限向四个方向延伸。现在我们在这个坐标系中lay out 几个项目。每个彩色矩形代表一个子视图:

Four rectangles with different colors and sizes placed at different coordinates in the coordinate system

   添加子视图的坐标系

写下下面的代码:

   

   UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
   redView.backgroundColor = [UIColor colorWithRed:0.815 green:0.007 blue:0.105 alpha:1];
    UIView *greenView = [[UIView alloc] initWithFrame:CGRectMake(150, 160, 150, 200)];
    greenView.backgroundColor = [UIColor colorWithRed:0.494 green:0.827blue:0.129 alpha:1];
    UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(40, 400, 200, 150)];
    blueView.backgroundColor = [UIColor colorWithRed:0.29 green:0.564blue:0.886 alpha:1];
    UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(100, 600, 180, 150)];
    yellowView.backgroundColor = [UIColor colorWithRed:0.972 green:0.905 blue:0.109 alpha:1];
    [mainView addSubview:redView];
    [mainView addSubview:greenView];
    [mainView addSubview:blueView];
    [mainView addSubview:yellowView];

  Bounds

    在UIView的文档中是这样描述Bounds的性质的:The bounds rectangle … describes the view’s location and size in its own coordinate system.  A view can be considered a window or viewport into a rectangular area of the plane defined by its coordinate system(一个视图可以被认为是一个窗口或把它看成一个坐标系中确定的平面区域)   And the viewʼs bounds express the location and size of this rectangle.(和视图界限表达这个矩形的位置和大小。)。

      说我们的视图的边界矩形具有320 ×480点的宽度和高度,它的起源是默认的( 0 , 0 ) 。的角度的视口进入坐标系平面中,显示整个面的一小部分。范围之外的一切都还在那里,只是隐藏

   A viewport of 320 by 480 points provides a viewport into the coordinate system. Some of the rectangles are inside the viewport and some outside.

  视图提供了一个由坐标系定义的视图入口即可见区域。没有看见的只是没有被渲染出来,但是仍然存在。

Frame

   接下来我们修改边界矩形的原点:

   CGRect.boud = mainView.bounds;

  bounds.origin = CGPointMake(0,100);

  mainView.bounds = bouds;

  矩形的边界原点现在还在(0,100)所以我们看到的场景看起来还像下面一样:

The viewport has moved down by 100 points, making a different area of the coordinate system visible.

  修改矩形边界的原点,相当于改变viewport

他看起来好像移动了100point,这里就是体现了真实的坐标系。但是实际上你看到的是保持固定的屏幕,看起来坐标系并没有发生改变。

Animation illustrating the movement of the coordinate system caused by a change of the bounds origin

   修改边界矩形的原点是相当于移动的坐标系中的方向相反,而视图的位置保持固定,因为它的frame不会改变。

  而这正是UIScrollView的做,当它滚动。注意,从看来好像视图的子视图被移动的用户的角度看,虽然其在的观点而言的位置的坐标系统(换言之,它们的frame)保持不变。

   

Letʼs Build UIScrollView


       滚动视图并不需要不断更新其子视图的坐标,使其滚动。所有它做的是调整其边界的起源。有了这些知识,实现一个非常简单的滚动视图是微不足道的。我们建立了一个手势识别来检测用户的平移手势,并响应这个手势,将我们通过拖动的量转化成视图的界限:

    

// CustomScrollView.h
@import UIKit;
@interface CustomScrollView : UIView
@property (nonatomic) CGSize contentSize;
@end
// CustomScrollView.m
#import "CustomScrollView.h"
@implementation CustomScrollView
- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self == nil) {
        return nil;
    }
    UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] 
        initWithTarget:self action:@selector(handlePanGesture:)];
    [self addGestureRecognizer:gestureRecognizer];
    return self;}
    - (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer{
    CGPoint translation = [gestureRecognizer translationInView:self];
    CGRect bounds = self.bounds;

    // Translate the view's bounds, but do not permit values that would violate contentSize   
    CGFloat newBoundsOriginX = bounds.origin.x - translation.x;
    CGFloat minBoundsOriginX = 0.0;
    CGFloat maxBoundsOriginX = self.contentSize.width - bounds.size.width;
    bounds.origin.x = fmax(minBoundsOriginX, fmin(newBoundsOriginX, maxBoundsOriginX));
    
    CGFloat newBoundsOriginY = bounds.origin.y - translation.y;
    CGFloat minBoundsOriginY = 0.0;
    CGFloat maxBoundsOriginY = self.contentSize.height - bounds.size.height;
    bounds.origin.y = fmax(minBoundsOriginY, fmin(newBoundsOriginY, maxBoundsOriginY));
    
    self.bounds = bounds;
    [gestureRecognizer setTranslation:CGPointZero inView:self];
    }
    
    @end

      就像真正的UIScrollView ,我们类有一个必须从外部设定来定义滚动区域的程度上contentSize属性。作为我们调整的范围,并确保这个值有效。

  下面是运行结果:

   Animated GIF showing our custom scroll view implementation

标签: UIScrollView入门
共有 人打赏支持
粉丝 12
博文 40
码字总数 36840
×
人生天地间
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: