文档章节

理解UIScrollView

人生天地间
 人生天地间
发布于 2014/05/11 20:13
字数 966
阅读 294
收藏 1

     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

© 著作权归作者所有

共有 人打赏支持
人生天地间
粉丝 12
博文 46
码字总数 42083
作品 0
常州
程序员
IOS中scrollsToTop问题小结

scrollsToTop小结: UIScrollView是用来展示滚动的一个类。他有UITableView、UITextView等子类。 scrollsToTop是UIScrollView的一个属性,主要用于点击设备的状态栏时,是scrollsToTop == Y...

Daniel_s
2016/04/29
29
0
iOS开发tips-UIScrollView的Autlayout布局

UIScrollViewj尽管继承于UIView,但它是一个相对比较特殊的视图,特别是当它遇到了AutoLayout之后。在UIScrollView中使用AutoLayout的目的除了使用相对约束确定子控件的位置和大小外,更重要...

jianxin160
2017/02/25
0
0
IOS中scrollsToTop问题小结

scrollsToTop小结: UIScrollView是用来展示滚动的一个类。他有UITableView、UITextView等子类。 scrollsToTop是UIScrollView的一个属性,主要用于点击设备的状态栏时,是scrollsToTop == Y...

Daniel_s
2015/12/25
102
0
一个多UITableview的左右滑动简单解决方案

前言 本文源自实际开发中的需求,核心的要求有几个: 1、多个UITableview要支持左右滑动; 2、点击Tab也要有UITableview的滑动切换效果; 3、每个UITableview单独的下拉刷新和上拉加载; 效果...

落影loyinglin
04/22
0
0
iOS解决方案:多个scrollview联动

前言 在移动应用实际开发过程中,往往会有多个scrollview嵌套的界面需求,这种需求已经司空见惯,解决方案也多种多样,这里就介绍一下我认为最优的解决方案。 效果图: Untitled.gif 结构解读...

indulge_in
2017/05/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

HashTable

Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射 Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口 Hashtable 的函数都是同步的,这意味着它是线...

职业搬砖20年
22分钟前
1
0
Linux系统状态查看命令1

10月23日任务 10.1 使用w查看系统负载 10.2 vmstat命令 10.3 top命令 10.4 sar命令 10.5 nload命令 查看系统负载 w命令 # 第一行:当前系统时间,系统启动时间,登录的用户,系统负载:1分钟...

robertt15
38分钟前
2
0
缓存那些事

前言 一般而言,现在互联网应用(网站或App)的整体流程,可以概括如图1所示,用户请求从界面(浏览器或App界面)到网络转发、应用服务再到存储(数据库或文件系统),然后返回到界面呈现内容...

Skqing
47分钟前
2
0
nginx开启stub_status模块配置方法

nginx开启stub_status模块配置方法 2017年12月13日 15:57:29 ly_dengle 阅读数:3765 标签: stub_statusnginxnginx开启stub_status模块 更多 个人分类: 软件工具php 版权声明:本文为博主原...

linjin200
53分钟前
3
0
挑逗 Java 程序员的那些 Scala 绝技

有个问题一直困扰着 Scala 社区,为什么一些 Java 开发者将 Scala 捧到了天上,认为它是来自上帝之吻的完美语言;而另外一些 Java 开发者却对它望而却步,认为它过于复杂而难以理解。同样是 ...

joymufeng
56分钟前
154
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部