zoukankan      html  css  js  c++  java
  • ScrollView

    http://www.cnblogs.com/dyf520/p/3805297.html

    一,创建和配置Scroll Views:
    1,创建Scroll Views:
    Scroll views的创建和其他view一样,通过代码或IB。只需要一点附加的配置来获得基本的scrolling能力。
    1)你必须设置contentSize属性。这个属性指定了可滑动区域的尺寸。
    2)你必须向Scroll views增加一个view或views来让其显示和滚动。

    2,在IB中创建Scroll views:
    拖动一个UIScrollView到目标区域。然后连接出口即可。
    虽然IB中的UIScrollView属性检查器允许你设置Scroll view的很多属性,你仍然需要在你的应用程序代码中负责设置contentSize属性,它定义了可滑动的区域。你可以在viewDidLoad方法中设置。

    Listing 1-1  设置a scroll view’s size
    - (void)viewDidLoad {
        [super viewDidLoad];
        UIScrollView *tempScrollView=(UIScrollView *)self.view;
        tempScrollView.contentSize=CGSizeMake(1280,960);
    }

    在设置了ScrollView的尺寸后,你的应用程序可以通过代码或在IB中添加必须的subview。

    3,通过代码创建ScrollView:

    Listing 1-2  通过代码创建ScrollView
    - (void)loadView {
        CGRect fullScreenRect=[[UIScreen mainScreen] applicationFrame];
        scrollView=[[UIScrollView alloc] initWithFrame:fullScreenRect];
        scrollView.contentSize=CGSizeMake(320,758);
        // do any further configuration to the scroll view
        // add a view, or views, as a subview of the scroll view.
        // release scrollView as self.view retains it
        self.view=scrollView;
        [scrollView release];
    }


    4,添加Subviews:
    无论你是使用一个子视图还是多个子视图,你都要面临一个决策性的设计:你的scrollView需要支持缩放吗?
    如果你准备支持缩放,通用的技术是使用一个单子视图覆盖整个contentSize,然后添加其他的子视图到这个view中。这允许你指定一个单独的”colloection”内容视图来进行缩放,并且其所有的子视图会根据它的状态进行缩放。
    如果不支持缩放,这就无关紧要了。

    5,配置ScrollView的Content Size,Content Inset和Scroll Indicators:
    contentSize属性是需要展示的内容区域的大小。
    你 或许向添加围绕scrollView边缘的padding,一般在顶部和底部设置,以便controllers和toolbars不会干扰查看整个 scrollView的内容.要添加padding,你必须设置contentInset属性。contentInset属性指定一个围绕在 scrollView的内容周围的buffer area。理解它的一个方法是,它使得scrollView的内容区域变大了,而无需更改其subView或其本身的尺寸。
    contentInset属性是一个 UIEdgeInsets结构,包括top,bottom,left,right字段。如下图所示:

     

    Scroll View Programming Guide for iOS--1 - supershll - 记忆里

     

    上 图指定了contentInset属性为(64,44,0,0),指定了顶部的64像素的buffer area(20px为status bar和44px为navigation controller的高度) ,和44px的底部的buffer area( 44px为toolbar的高度).设置语句如下:
    scrollView.contentInset=UIEdgeInsetsMake(64.0,0.0,44.0,0.0);
    (contentInset属性应该是增加scrollview的可滚动区域,但是内容不会显示在contentInset区域内,所以在注册键盘弹出事件时,一般先给scrollView增加一个键盘高度的contentInset)

    然 而,更改contentInset的值对显示scroll Indicator有一个非预期的影响。当你拖动scroll view时,会显示滚动指示器(scroll indicator).滚动指示器会显示于任何显示在contentInset定义的区域内的视图之下,如navigation Control和toolbar会遮挡滚动指示器的显示。
    要修正这个,你必须设置scrollIndicatorInsets属性。scrollIndicatorInsets属性也是一个UIEdgeInSets结构。一般将这个属性设置成和contentInset属性一致,以正确显示滚动指示器。
    scrollView.scrollIndicatorInsets=UIEdgeInsetsMake(64.0,0.0,44.0,0.0);

    二,滚动ScrollView的内容
    用 户操作有drag,flick(快速移动).flick手势操作不仅引起scroll view的滚动,而且引起一个动力,基于移动的速度,虽然手势完了,但是滚动一直继续,直到减速为0时停止。在减速期间,用户可以触摸屏幕以停止滚动在某 处。所有这些行为已经内嵌于UIScrollView,并且无需开发人员实现。
    但有时需要使用代码滑动内容,展示文档的某一特定的部分。在这些情况下,UIScrollView提供了必须的方法。
    UIScrollView的代理协议UIScrollViewDelegate提供了方法,允许你的代码跟踪滚动进度和正确响应。
    1,滚动到一个特定的偏移距离:滚动到一个特定的top-left(距离左上角的)位置(contentOffset属性)可以通过两种方法完成:
    a)方法setContentOffset:animated: 无论是否动画,代理都被发送一个scrollViewDidScroll:消息。如果动画被禁用,或者你直接设置了contentOffset属性,代理只接收到一个单独的scrollViewDidScroll:消息,如果启用了动画,代理将在动画执行期间收到一系列的scrollViewDidScroll:消息。当动画执行完毕后,代理收到一个scrollViewDidEndScrollingAnimation:消息。
    B)使矩形可见:这在你的应用需要显示一个特定的控制视图时非常有用。方法scrollRectToVisible:animated: 滚动指定的矩形以使其正好显示在scroll View中。委托收到的消息同上。

    2,滚动到顶部:如果status bar可见,那么可以通过轻击status bar来快速滚动scroll view到顶部。你的应用要更改这个特性,需要实现代理方法scrollViewShouldScrollToTop:并返回YES或NO。
    当滚动完成时,代理被发送一个scrollViewDidScrollToTop:消息。

    3,在滚动时委托被发送的消息:当滚动发生时,scrollView跟踪其状态,通过使用tracking,dragging,decelerating,和zooming属性。另外,contentOffset属性定义了可见内容的top-left点(这个属性是实时改变的)。下面的表格描述了每个状态属性:

    属性                   描述
    tracking     YES—如果用户的手指在接触屏幕
    dragging     YES—如果用户的手指接触屏幕并且移动
    decelerating  YES—如果scrollView正在减速动画
    zomming     YES—如果scrollView正在tracking一个捏合手势来更改其zoomScale属性
    contentOffset  一个到scroll View bounds的左上角的CGPoint

    没有必要轮询这些属性来确定正在进行的动作因为scrollview发送详细的一系列消息给代理,来指示滚动动作的进度。委托方法可以查询这些状态属性来确定为什么接收到消息或scrollview当前在哪里。

    4,简单的途径:跟踪一个滚动动作的开始和结束:如果你的应用只关心滚动过程的开始和结束,你可以只实现很少的几个委托方法
    1)实现 scrollViewWillBeginDragging:来接收拖动将要开始的通知
    2)要确定滚动是否已经停止,你必须实现两个委托方法:scrollViewDidEndDragging:willDecelerate:scrollViewDidEndDecelerating: .当委托收到scrollViewDidEndDragging:willDecelerate:消息并且decelerate参数为NO,或者当委托收到scrollViewDidEndDecelerating:方法时,滚动就结束了。

    5,完全的委托消息序列:
    当用户触摸屏幕时,tracking sequence就开始了。Tracking属性被立即设置为YES,并在用户手指触摸屏幕期间保持YES,无论是否移动了手指。
    如果用户的手指保持静止,并且内容视图响应触摸事件,它应该处理触摸,并且序列完成。
    然而,如果用户移动了手指,序列就继续进行。
    当用户开始移动手指来发起滚动scrollview的第一次尝试(假定scrollview的默认值)来取消任何触摸处理进度,如果它尝试这么做。

    (注 意:贯穿整个消息序列,这是可能的—即tracking和dragging属性一直为NO,并且zooming属性为YES。这发生于当缩放动作的结果导 致scrolling发生时,无论Scrolling是被一个手势引起还是通过代码引起。作为zooming或scrolling的结果,如果代理被发送 消息,你的应用或许选择采取不同的行动。)

    scrollView的dragging属性设置为YES,并且发送给代理 scrollViewWillBeginDragging:消息。
    随 着用户拖动其手指,scrollViewDidScroll:消息发送给其代理。在滚动期间,这个消息持续的发送。这个方法的你的实现可以查询 scrollView的contentOffset属性来确定scrollView的bounds的左上角。ContentOffset属性一直是 scroll bounds的左上角位置,无论是否正在滚动。

    (总结1:即普通拖动手指(不是缩放),信息序列为:
    1)手指放到屏幕上Tracking=YES。如果scrollView正在滚动,那么这会引起scrollView停止滚动,代理会收到
    scrollViewDidEndDecelerating:消息。
    2)如果用户开始拖动手指,dragging=YES同时scrollViewWillBeginDragging: 消息发出。代理可以取消拖动
    3)如果允许拖动,那么消息scrollViewDidScroll:持续发送给代理,你可以通过contentOffset属性来帮助你处理该消息。
    4)拖动完成,代理收到scrollViewDidEndDragging:willDecelerate: 并且第二个参数为NO,表示拖动结束。
    5) 如果用户的操作是flick(即快速滑动了手指,并离开屏幕),那么代理收到 scrollViewDidEndDragging:willDecelerate:,并且第二个参数为NO,表示拖动结束,开始减速。此时 Tracking=NO,委托收到scrollViewWillBeginDecelerating:消息,在减速期间,委托持续收到 scrollViewDidScroll:消息,并在减速结束后,委托收到scrollViewDidEndDecelerating:消息
    6)如果是使用代码setContentOffset:animated:或
    scrollRectToVisible:animated: 导致的scrollView滚动,如果动画被禁用,或者你直接设置了contentOffset属性,代理只接收到一个单独的scrollViewDidScroll:消息,如果启用了动画,代理将在动画执行期间收到一系列的scrollViewDidScroll:消息。当动画执行完毕后,代理收到一个scrollViewDidEndScrollingAnimation:消息。
    )


    如 果用户执行了一个flick手势,tracking属性被设置为NO,因为为了执行flick手势,用户的手指必须离开屏幕。这是委托收到 scrollViewDidDragging:willDecelerate:消息。在滚动减速时参数deceleration将是YES。减速度通过decelerationRate属性控制。默认地,这个属性被设置为UIScrollViewDecelerationRateNormal。你可以设置其为UISCrollViewDecelerationFast来加快减速。在减速期间,decelerating属性为YES。
    如果用户拖动,停止拖动并且离开屏幕,委托将收到scrollViewDidEndDragging:willDecelerate:消息,deceleration参数为NO。这是因为没有引起冲力。因为用户的手指已经不再屏幕上,tracking属性为NO。
    如果scrollViewDidEndDragging:willDecelerate:消息的减速参数为NO,然后委托将不再收到这个拖动操作的委托消息。ScrollView的decelerating属性现在也返回NO。

    还 有一个情况导致scrollViewDidEndDragging:willDecelerate:消息发送给代理,甚至用户已经在静止状态下提高了手 指。如果scroll View被配置为提供可见的cue of bouncing ----当用户拖动内容超出scrolling area的边缘时,scrollViewDidEndDragging:willDecelerate:消息被发送给代理并且deceleration参 数为YES。当bounces属性为YES(默认值)时Bouncing被启用。当bounces属性为NO时,alwaysBounceVerticalalwaysBounceHorizontal属性不影响scrollview的行为。当bounces属性为YES时,当contentSize属性小于scroll view的bounds时,他们允许bouncing。
    不 管哪种情况导致scroll view接收scrollViewDidEndDragging:willDecelerate:消息,如果deceleration参数为 YES,scroll view都被发送scrollViewWillBeginDecelerating:消息。在减速期间,委托持续收到 scrollViewDidScroll:消息,虽然tracking和dragging属性都是NO。decelerating属性持续为YES。
    最终,当ScrollView减速完成时,委托被发送一个scrollViewDidEndDecelerating:消息,并且decelerating属性为NO,并且滚动序列完成。


    三、使用捏合手势基本的缩放
    UIScrollView支持捏合手势,你的应用指定缩放因子并且你实现一个单独的委托方法。
    1,支持捏合缩放手势:
    要支持缩放,你必须为你的ScrollView设置一个代理。代理必须遵循UIScrollViewDelegate协议。代理类必须实现viewForZoomingInScrollView:方法并且返回要zoom的view。

    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
    {
        return self.imageView;
    }

    要指定用户可以缩放的amount,你可以设置minimumZoomScale和maximumZoomScale属性,他们默认为1.0.可以在IB中设置这些值,或通过代码。
    指定缩放因子和代理实现viewForZoomingInScrollView:方法是实现缩放的最小的要求。

    2, 通过代码缩放:一个scrollView可能需要缩放来响应触摸事件,例如双击或其他轻击手势,或响应另外一个用户动作而不是捏合手势。要允许这 些,UIScrollView提供了一个两个实现方法:setZoomScale:animted:和zoomToRect:animated:
    setZoomScale:animted: 设置当前的zoom scale为指定值。值必须在指定的minimumZoomScale和maximumZoomScale之间,还可以直接设置zoomScale属性, 相当于参数为NO。当缩放时,被缩放的view的中心保持不变。
    zoomToRect:animated:方法缩放内容来填充指定的矩形。下面是例子:

    Listing 3-2  A utility method that converts a specified scale and center point to a rectangle for zooming
    - (CGRect)zoomRectForScrollView:(UIScrollView *)scrollView withScale:(float)scale withCenter:(CGPoint)center {
        CGRect zoomRect;
        // The zoom rect is in the content view's coordinates.
        // At a zoom scale of 1.0, it would be the size of the
        // imageScrollView's bounds.
        // As the zoom scale decreases, so more content is visible,
        // the size of the rect grows.
        zoomRect.size.height = scrollView.frame.size.height / scale;
        zoomRect.size.width  = scrollView.frame.size.width  / scale;
        // choose an origin so as to get the right center.
        zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0);
        zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
        return zoomRect;
    }
    }

    3,通知代理缩放完成:代理收到 scrollViewDidEndZooming:withView:atScale:消息。

    4,确保被缩放的内容is Sharp—当其被缩放时:
    当 scrollView的内容被缩放时,被缩放的视图内容只是简单地被缩放。这只是创建更大或更小的内容,但不导致内容重画。结果是,显示的内容is not displayed sharply。当缩放的内容是一幅图像时,并且你的应用并不显示新的,更详细的内容,例如地图应用,这可能不一个问题。
    然 而,如果你缩放的内容被实时绘制,并且需要在被缩放时显示sharply,你的应用需要使用Core Animation。它需要更改Core Animation---通过UIView的layer to CATileLayer and 通过Core Animation的drawLayer:inContext:方法绘制。

    Listing 3-3  Implementation of a UIView Subclass That Draw’s Its Content Sharply During Zoom
    #import "ZoomableView.h"
    #import <QuartzCore/QuartzCore.h>
     
    @implementation ZoomableView

    // Set the UIView layer to CATiledLayer
    +(Class)layerClass
    {
        return [CATiledLayer class];
    }
     
     
    // Initialize the layer by setting
    // the levelsOfDetailBias of bias and levelsOfDetail
    // of the tiled layer
    -(id)initWithFrame:(CGRect)r
    {
        self = [super initWithFrame:r];
        if(self) {
            CATiledLayer *tempTiledLayer = (CATiledLayer*)self.layer;
            tempTiledLayer.levelsOfDetail = 5;
            tempTiledLayer.levelsOfDetailBias = 2;
            self.opaque=YES;
        }
        return self;
    }
     
    // Implement -drawRect: so that the UIView class works correctly
    // Real drawing work is done in -drawLayer:inContext
    -(void)drawRect:(CGRect)r
    {
    }
     
    -(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
    {
        // The context is appropriately scaled and translated such that you can draw to this context
        // as if you were drawing to the entire layer and the correct content will be rendered.
        // We assume the current CTM will be a non-rotated uniformly scaled
     
       // affine transform, which implies that
        // a == d and b == c == 0
        // CGFloat scale = CGContextGetCTM(context).a;
        // While not used here, it may be useful in other situations.
     
        // The clip bounding box indicates the area of the context that
        // is being requested for rendering. While not used here
        // your app may require it to do scaling in other
        // situations.
        // CGRect rect = CGContextGetClipBoundingBox(context);
     
        // Set and draw the background color of the entire layer
        // The other option is to set the layer as opaque=NO;
        // eliminate the following two lines of code
        // and set the scroll view background color
        CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
        CGContextFillRect(context,self.bounds);
     
        // draw a simple plus sign
        CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
        CGContextBeginPath(context);
        CGContextMoveToPoint(context,35,255);
        CGContextAddLineToPoint(context,35,205);
        CGContextAddLineToPoint(context,135,205);
        CGContextAddLineToPoint(context,135,105);
        CGContextAddLineToPoint(context,185,105);
        CGContextAddLineToPoint(context,185,205);
        CGContextAddLineToPoint(context,285,205);
        CGContextAddLineToPoint(context,285,255);
        CGContextAddLineToPoint(context,185,255);
        CGContextAddLineToPoint(context,185,355);
        CGContextAddLineToPoint(context,135,355);
        CGContextAddLineToPoint(context,135,255);
        CGContextAddLineToPoint(context,35,255);
        CGContextClosePath(context);
        // Stroke the simple shape
        CGContextStrokePath(context);
    }

    五,Scrolling Using Paging Mode:
    UIScrollView支持Paging模式,你需要设置pagingMode为YES。
    contentSize属性需要设置为宽度= width*pages 高度=height*1。
    额外地,scroll Indicator应该被禁用(使用showHorizontalIndicator和showVerticalIndicator=NO),因为在用户触摸屏幕时相对位置是不相关的,或者使用UIPageControl来显示。
    一 个paging scroll view的subviews可以通过两种方法配置:如果内容是小的,你可以一次性绘制所有的内容到一个视图中,这个视图的大小就是scroll view的contentSize大小。当然这是最初的实现方法,当处理大的内容区域时,或页面内容需要时间绘制时,这种方法是不够效率的。
    上述两种情况以及累死情形,你应该使用多视图来展示内容,每个page一个view。
    假定在一个paging scroll view里有很多很多pages,可以只通过3个view实例来得到:当scroll view controller被初始化后,所有的3个视图被创建和初始化。一般这些视图是UIView的子视图。
    因为用户滚动内容,要确定什么时候页需要被重新配置,scroll view需要一个代理实现 scrollViewDidScroll:方法。这个方法需要跟踪contentOffset属性,并且在其超过中间的点的时候,视图应该被重新配置。
    如果绘制页面内容是耗时的操作,你的应该应该增加额外的视图到视图池,指示这些。

     
     
     
  • 相关阅读:
    PostgreSQL中的partition-wise join
    Partition-wise join
    外观模式 门面模式 Facade 结构型 设计模式(十三)
    桥接模式 桥梁模式 bridge 结构型 设计模式(十二)
    组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)
    创建型设计模式对比总结 设计模式(八)
    原型模式 prototype 创建型 设计模式(七)
    单例模式 创建型 设计模式(六)
    建造者模式 生成器模式 创建型 设计模式(五)
    抽象工厂模式 创建型 设计模式(四)
  • 原文地址:https://www.cnblogs.com/Cheetah-yang/p/4657748.html
Copyright © 2011-2022 走看看