ScrollView

一,创建和配置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时,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属性,并且在其超过中间的点的时候,视图应该被重新配置。
如果绘制页面内容是耗时的操作,你的应该应该增加额外的视图到视图池,指示这些。
六,Nesting Scroll Views:

原文地址: http://supershll.blog.163.com/blog/static/3707043620131196456702/

时间: 2024-08-24 06:08:36

ScrollView的相关文章

Android零基础入门第61节:滚动视图ScrollView

原文:Android零基础入门第61节:滚动视图ScrollView 前面几期学习了ProgressBar系列组件.ViewAnimator系列组件.Picker系列组件和时间日期系列组件,接下来几期继续来学习常见的其他组件. 一.ScrollView概述 从前面的学习有的同学可能已经发现,当拥有很多内容时屏幕显示不完,显示不全的部分完全看不见.但是在实际项目里面,很多内容都不止一个屏幕宽度或高度,那怎么办呢?那就需要本节学习的ScrollView来完成. 在默认情况下,ScrollView只是

Android ScrollView 滚动到顶部

有时候使用ScrollView,里边控件比较多的时候,打开界面,会滑到底部,如果要设置滑动到顶部,一般有两种方法 1.使用fullScrol(),scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部 scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部 需要注意的是,该方法不能直接被调用 因为Android很多函数都是基于消息队列来同步,所以需要一部操作, addView完之后,不等于马上就会显示,而是在

Android仿qq回弹阻尼ScrollView

仿qq写一个可以来回弹的ScrollView. 只需要重写ScrollView: public class MyScrollView extends ScrollView {     // y方向上当前触摸点的前一次记录位置     private int previousY = 0;     // y方向上的触摸点的起始记录位置     private int startY = 0;     // y方向上的触摸点当前记录位置     private int currentY = 0;    

Android的GridView和ScrollView的嵌套

来源于回答频道答题,因此内容都是基于回答频道的原题布局进行 1.布局文件如下 文件名:testxm.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" andr

一句话让你的ScrollView、ListView弹力十足

android默认的ScrollView.ListView在最顶端下拉或者最底端上拉的时候,都不会带有反弹效果,很生硬的让你不能继续拖动,不像iOS那样可以回弹,个人认为,iOS的交互还是略好一点,那么我们也来在Android下实现下这个功能,先看下效果图: 那么我们今天的目标是一句话实现,如何去做呢 我们还是先看下代码: package com.xys.flexible; import android.content.Context; import android.util.Attribute

Android 控制ScrollView滚动到底部

这里有两种办法,第一种,使用scrollTo(): ublic static void scrollToBottom(final View scroll, final View inner) { Handler mHandler = new Handler(); mHandler.post(new Runnable() { public void run() { if (scroll == null || inner == null) { return; } int offset = inner

cocos2d js ScrollView的使用方法

游戏中非常多须要用到ScrollView的情况,也就是须要滚动一片区域. 这里有两种实现方法,一种是使用cocos studio的方式,另外一种是手写代码.先看第一种 第一种记得在设置滚动区域时选取裁剪项. var size = cc.winSize; //读取json文件 var root = ccs.uiReader.widgetFromJsonFile(res.listJson); this.addChild(root); //获取在cocos studio里面设定好的scrollView

微信小程序-scroll-view横向滚动和上拉加载

今天介绍微信小程序中scroll-view实现横向滚动和上拉加载的实现及需要注意的地方. 先看最终效果. 横向滚动 1.设置滚动项display:inline-block; 2.设置滚动视图容器white-space: nowrap; 3.滚动项不要用float 为什么会有以上三点要求呢? 其实横向滚动官方文档中是没有做太多说明的,只说明需要定义scroll-view滚动方向scroll-x=true允许横向滚动,但是我在实践的时候我发现,你要横向滚动,首先你得是一排吧.所以才发现需要定义滚动项

Android 横向ScrollView照片浏览器实现(致敬郭神)

因为项目中需要用到所以实现的一个横向的照片浏览器,使用横向SrollView实现. 实现效果如下: 实现思路: 在开始做之前呢,本着有轮子就用轮子的精神,也还是去百度找了很久,诸如"Android横向照片墙"."Android横向照片流"."Android横向照片选择器"-完全没有好咩..查来查去都是那几篇竖向照片瀑布流的,横向的反正我是没找到. 然后,在将郭神的<ndroid瀑布流照片墙实现,体验不规则排列的美感>一文拜读之后(ht

安卓使ScrollView滚动到底部代码

在开发中,我们经常需要更新列表,并将列表拉倒最底部,比如发表微博,聊天界面等等, 这里有两种办法,第一种,使用scrollTo(): public static void scrollToBottom(final View scroll, final View inner) { // 何问起 hovertree.com Handler mHandler = new Handler(); mHandler.post(new Runnable() { public void run() { if (