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字段。如下图所示:
上 图指定了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时,alwaysBounceVertical和alwaysBounceHorizontal属性不影响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属性,并且在其超过中间的点的时候,视图应该被重新配置。如果绘制页面内容是耗时的操作,你的应该应该增加额外的视图到视图池,指示这些。
转载于:https://www.cnblogs.com/Cheetah-yang/p/4657748.html
相关资源:android scrollview 上拉下拉刷新