亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS中UIScrollerView的用法及基于AotoLayout的控件懸停

2020-07-26 03:25:43
字體:
來源:轉載
供稿:網友

UIScrollView為了顯示多于一個屏幕的內容或者超過你能放在內存中的內容。Scroll View為你處理縮小放大手勢,UIScrollView實現了這些手勢,并且替你處理對于它們的探測和回應。其中需要注意的子類是UITableView以及UITextView(用來顯示大量的文字)。還有一個UIWebView,盡管那不是UIScrollView的直接子類,它適用UIScrollView去顯示網頁內容contentsize是內容的寬和高,contentsize.width是內容的寬度,contentsize.heght是高度,contentsize是UIScrollView的一個屬性,它是一個CGSize,是由核心圖形所定義的架構,那定義了你可以滾軸內容的寬度和高度,你也可以添加可以上下滾動的額外區域。第一種方法是你可以通過添加內容的大小來完成。另外一個比較動態的選擇是UIScrollView的另一個屬性contentInset,contentInset增加你在contentsize中指定的內容能夠滾動的上下左右區域數量contentInset.top以及contentInset.buttom分別表示上面和下面的距離。

201631792637325.jpg (800×511)

在滾軸視圖中,有一個叫做ContentOffset的屬性跟蹤UIScrollView的具體位置,你能夠自己獲取和設置它,ContentOffset是你當前可視內容在滾軸視圖邊界的左上角那個點。如圖:

201631792701451.png (600×534)

可以看出,ContentOffset內容中的那個點不是從contentInset的左上角開始的,而是內容的左上角,此時的ContentOffset是正值,但有時也是負值,如下圖所示:

201631792728922.png (600×528)

使用一個ScrollView
創建一個UIScrollView

復制代碼 代碼如下:

CGRectframe = CGRectMake( 0, 0, 200, 200);
scrollView= [[UIScrollView alloc] initWithFrame: frame];

添加子視圖(框架可以超過scroll view的邊界)
復制代碼 代碼如下:

frame= CGRectMake( 0, 0, 500, 500);
myImageView= [[UIImageView alloc] initWithFrame: frame];
[scrollViewaddSubview:myImageView];

設置內容尺寸
復制代碼 代碼如下:

scrollView.contentSize= CGSize(500,500);

擴展Scroll View 的行為

  • 應用程序通常需要知道有關的滾圖的事件
  • scrolloffset改變的時候
  • 拖動開始和結束
  • 減速的開始和結束

通過子類化擴展Scroll View 的行為

  • 創建一個子類
  • 重寫一些功能并改變行為
  • 關于這種方式的爭議

應用程序的邏輯和行為變成了視圖本身的一部分,就像,你可能有一些定制的滾軸邏輯,,在那你只在意一個視圖控制,但你想在不同地方重復使用你的滾軸視圖,如果你必須為每個都子類化,你最后會有很多不同的滾軸視圖子類以及在視圖中的特定應用邏輯。

編寫很多子類是很沉悶的事情,你最后會有很多無法重復使用的單獨視圖,而MVC的視圖部分的一個重點是視圖是可以在不同的控制器和不同的模式之中重復使用的,如果我們把所有邏輯都放在視圖中,它減少了可復用性。

你的代碼變得很牢固地配對在一起,它實際上變成了超類的一部分,你無法從UIScrollView中析取它,之后用其它東西代替,如果它在你控制器中且為控制器的一部分,在之后更容易改變它工作的方式和重新安排你應用程序的一些部分。

通過委派來擴展Scroll View 的行為(常用的)
委派是一個單獨的對象,協議,定義了委派會實現的一系列功能的Objective-C協議,它創建了一系列很清晰的撤銷點,在那里你能定制行為和外觀。它在這些對象之間保持了松散的配對,視圖本身與視圖控制器或任何其它的控制器對象,委派不是滾軸視圖的直接子類,它比起牢固配對的子類更加的松散。


理論篇
在滾動的過程中,實際上就是contentOffset的值在不斷變化,當手指觸摸后,UIScrollView會暫時攔截觸摸事件,使用一個計時器。假如在計時器到點后沒有發生手指移動事件,那么UIScrollView發送 tracking events 到被點擊的 subview 上面。如果在計時器到點前發生了移動事件,那么UIScrollView取消 tracking 然后自己發生滾動。

可以重載子類

復制代碼 代碼如下:

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view;

決定自己是否接受 touch 事件
復制代碼 代碼如下:

- (BOOL)touchesShouldCancelInContentView:(UIView *)view;

開始發送 tracking messages 給 subview 的時候調用這個方法,決定是否發送 tracking messages 消息到 subview。
返回NO -> 發送,表示不取消
返回YES -> 不發送,表示會取消

屬性篇

復制代碼 代碼如下:

@property(nonatomic,readonly,getter=isTracking) BOOL tracking;

當 touch 后還沒有拖動的時候值是YES,否則NO
復制代碼 代碼如下:

@property(nonatomic,readonly,getter=isZoomBouncing) BOOL zoomBouncing;

當內容放大到最大或者最小的時候值是YES,否則NO
復制代碼 代碼如下:

@property(nonatomic,readonly,getter=isZooming) BOOL zooming;

當正在縮放的時候值是YES,否則NO
復制代碼 代碼如下:

@property(nonatomic,readonly,getter=isDecelerating) BOOL decelerating;

當滾動后,手指放開但是還在繼續滾動中。這個時候是YES,其他時候是NO
復制代碼 代碼如下:

@property(nonatomic) CGFloat decelerationRate;

設置手指放開后的減速率
復制代碼 代碼如下:

@property(nonatomic) CGFloat maximumZoomScale;

表示放大的最大倍數
復制代碼 代碼如下:

@property(nonatomic) CGFloat minimumZoomScale;

表示縮小的最小倍數
復制代碼 代碼如下:

@property(nonatomic,getter=isPagingEnabled) BOOL pagingEnabled;

當值為YES的時候,就會產生翻頁那種效果
復制代碼 代碼如下:

@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled;

決定是否可以滾動
復制代碼 代碼如下:

@property(nonatomic) BOOL delaysContentTouches;

當值為YES的時候,用戶一旦觸碰,然后再一定時間內沒有移動,UIScrollView會發送 tracking events,然后用戶移動手指足夠長度觸發滾動事件,這個時候,UIScrollView發送了-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event到 subview,然后UIScrollView開始滾動。假如值為NO,UIScrollView發送 tracking events 后,就算用戶移動手指,UIScrollView也不會滾動。
復制代碼 代碼如下:

@property(nonatomic) BOOL showsHorizontalScrollIndicator;

滾動時是否顯示水平滾動條
復制代碼 代碼如下:

@property(nonatomic) BOOL showsVerticalScrollIndicator;

滾動時是否顯示垂直滾動條
復制代碼 代碼如下:

@property(nonatomic) BOOL bounces;

默認是YES,就是滾動超過邊界會有反彈回來的效果,如果設置為NO,那么滾動到邊界就會立刻停止
復制代碼 代碼如下:

@property(nonatomic) BOOL bouncesZoom;

這個效果反映在縮放上面,如果縮放超過最大縮放,就會有反彈效果,加入設置為NO,則達到最大或者最小的時候立刻停止
復制代碼 代碼如下:

@property(nonatomic,getter=isDirectionalLockEnabled) BOOL directionalLockEnabled;

默認是NO,可以在垂直和水平方向同時運動。當值為YES的時候,加入一開始是垂直或者水平運動,那么接下來會鎖定另外一個方向的滾動。加入一開始是對角方向滾動,則不會禁止某個方向
復制代碼 代碼如下:

@property(nonatomic) UIScrollViewIndicatorStyle indicatorStyle;

滾動條的樣式,基本只是設置顏色
復制代碼 代碼如下:

@property(nonatomic) UIEdgeInsets scrollIndicatorInsets;

設置滾動條的位置

方法篇
直接上代碼看

復制代碼 代碼如下:

#pragma mark UIScrollViewDelegate
//只要滾動了就會觸發
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;  
{
//    NSLog(@" scrollViewDidScroll");
    NSLog(@"ContentOffset  x is  %f,yis %f",scrollView.contentOffset.x,scrollView.contentOffset.y);
}
//開始拖拽視圖
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;  
{
   NSLog(@"scrollViewWillBeginDragging");
}
//完成拖拽
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
   NSLog(@"scrollViewDidEndDragging");
}
//將開始降速時
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;  
{
   NSLog(@"scrollViewWillBeginDecelerating");
}

//減速停止了時執行,手觸摸時執行
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;  
{
   NSLog(@"scrollViewDidEndDecelerating");
}

//滾動動畫停止時執行,代碼改變時出發,也就是setContentOffset改變時
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
{
   NSLog(@"scrollViewDidEndScrollingAnimation");
}

//設置放大縮小的視圖,要是uiscrollview的subview
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;  
{
   NSLog(@"viewForZoomingInScrollView");
    return viewA;
}

//完成放大縮小時調用
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    viewA.frame=CGRectMake(50,0,100,400);
   NSLog(@"scale between minimum and maximum. called after any 'bounce' animations");
}// scale between minimum and maximum. called after any 'bounce' animations

//如果你不是完全滾動到滾軸視圖的頂部,你可以輕點狀態欄,那個可視的滾軸視圖會一直滾動到頂部,那是默認行為,你可以通過該方法返回NO來關閉它
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;  
{
    NSLog(@"scrollViewShouldScrollToTop");
   returnYES;
}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;    
{
    NSLog(@"scrollViewDidScrollToTop");
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
   // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

基于AotoLayout的控件懸停

在很多的電商類的APP中我們經常會用到一種滑動懸停的效果,所以這次嘗試著利用AutoLayout來實現這種效果。話不多說先上圖
效果:

效果上過了,還是理順下思路上吧。從效果圖上不難發現我們的程序是基于UIScrollerView的。界面上的展示同樣都是UIScrollView的子控件。當然了難點也就是基于UIScrollerView的內部子控件的布局以及AutoLayout約束的修改。
我們看一下我們的需要的一些基本的控件布局:

201631792751040.png (209×187)

好了,現在開始開始搭建新的項目了,首先在Storyboard上搭建最基本的布局,并將控件基本布局到相應的位置,以備我們更方便的添加約束。

201631792812291.png (708×707)

到了這里就開始對我們的控件添加基本的約束了從上開始吧。上面的控件我們能確定是UIImageView的heigth以及top、left以及rihgt。至于bottom到了后面會著重設置的。

201631792836036.png (269×265)

然后繼續來操作懸停的View。這個View因為處在兩個view的中間所以我們要暫時確定height以及left和right的約束就足夠了了

201631792858728.png (268×235)

終于到最后一個UIImageView了,同樣的能確定的是height、right、left以及bottom這四項。

201631792924074.png (260×249)

到了這里針對單個的控件的布局基本完成了,細心的你可能會發現以上的操作都沒有進行關聯以及沒有對width進行約束。那么下面我們就要開始進行三者的關聯以及width上的設置。
因為懸停的view處與兩個imageView的中間,所以我們只需要對它進行處理就好了

201631792943377.png (257×274)

其實這兩個約束完全是可以在設置懸停view的時候的添加,之所以在這里添加是我們在后面的控制器會用到這兩個約束,為了好辨認我們就給他們定義上別名:

201631793001079.png (234×78)

然后我們按住command選擇我們的三個控件然后按住control拖向scrollView的父控件view設置等width。

201631793021388.png (335×256)

好了,到了這里我們的約束已經不會再報錯了,然后在邏輯上也是基本是通順的了,但是對于我們懸停的功能來說就少了關鍵的一個環節那么就是一旦懸停view懸停了,那么它與上下兩個imageView的約束要怎么處理呢?所以我們還需要一個輔助的約束用來懸停之后的關聯處理

201631793036900.png (639×578)

添加之后我們給這個約束起個別名hidden懸停,不過細心的你一定會發現添加之后會sb會提示出有沖突的約束,那么我們只需要對我們剛剛添加的約束進行一下操作就OK了

201631793055342.png (244×279)

好了,到了這里我們在AutoLayout上要做的事情就這些了,下面我們就可以安心的寫代碼了。

復制代碼 代碼如下:

@interface ViewController ()/**中間的View*/@property (weak, nonatomic) IBOutlet UIView *centreView;/**上面的ImageView*/@property (weak, nonatomic) IBOutlet UIImageView *topImageView;/**centreView的top約束*/@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;/**centreView的bottom約束*/@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomConstraint;/**topImageView暫禁用的約束*/@property (weak, nonatomic) IBOutlet NSLayoutConstraint *hiddenConstraint;
@end

然后在scrollView的滑動代理方法中實現
復制代碼 代碼如下:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //獲得top圖片的高度
    CGFloat imageH = self.topImageView.frame.size.height;
    //獲取偏移量
    CGFloat offsetY = scrollView.contentOffset.y;
    //centrView的frame
    CGRect centreFrame = self.centreView.frame;
    if (offsetY>=imageH) {
        //將centreView的向上和向下的約束禁用
        self.bottomConstraint.active = NO;
        self.topConstraint.active = NO;
        //將topImageView與bottomImageView的約束使用關聯
        self.hiddenConstraint.active = YES;
        //懸停在位置
        centreFrame.origin.y = 0;
        self.centreView.frame = centreFrame;
        //添加在scrollView的父控件
        [self.view addSubview:self.centreView];
    }else{
        //添加在topIamgeView的下面
        centreFrame.origin.y = imageH;
        self.centreView.frame = centreFrame;

        [scrollView addSubview:self.centreView];
        //記住一定要先添加到scrollView上之后在修改約束的內容,不然添加的約束會不成,因為系統無法建立他們之間的聯系。
        self.hiddenConstraint.active = NO;
        self.topConstraint.active = YES;
        self.bottomConstraint.active = YES;

    }
    //等比例的伸縮
    CGFloat scale= 1-(offsetY/60);
    scale = (scale>=1)?scale :1;
    self.topImageView.transform = CGAffineTransformMakeScale(scale, scale);

}


最后補充:

在子控件的尺寸不能通過UIScrollView來計算,可以通過以下方式計算

  • 設置固定值(width==100,height==300)
  • 相對于UIScrollView以外的其他控件來計算尺寸

在UIScrollView里面布局子控件,sb里面默認是是需要子控件的尺寸以及子控件與UIScrollView之間的間距來計算出scroller的conentSize的。所以這就是上面的子控件要與父控件來等寬的原因了。
UIScrollView的frame應該通過子控件以外的其他控件來計算。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久天天躁狠狠躁夜夜躁| 亚洲男人天堂网站| 欧美成人精品在线| 92看片淫黄大片欧美看国产片| 国产精品久久久久久超碰| 久久免费精品视频| 日本a级片电影一区二区| 国产精品吊钟奶在线| 在线精品91av| 亚洲欧洲一区二区三区在线观看| 91色中文字幕| 欧美成人一二三| 欧美人与物videos| 欧美电影院免费观看| 欧美日韩激情小视频| 国产精品xxx视频| 日本在线观看天堂男亚洲| 欧美激情一区二区三区久久久| 国产精品久久久久久久app| 狠狠躁18三区二区一区| 亚洲国产精品久久久久秋霞不卡| 亚洲精品一区av在线播放| 亚洲一区二区在线播放| 欧美成人免费小视频| 91欧美日韩一区| 日韩中文字幕视频在线观看| 成人av番号网| 亚洲人成五月天| 久久久久久久一区二区三区| 夜夜躁日日躁狠狠久久88av| 精品日韩美女的视频高清| 国产精品入口尤物| 91在线观看免费高清| 欧美亚洲在线播放| 欧美一级免费视频| 亚洲第一精品夜夜躁人人爽| 亚洲精品一区二区久| 成人在线一区二区| 88国产精品欧美一区二区三区| 久久九九有精品国产23| 久久天天躁狠狠躁夜夜躁| 国产精品18久久久久久麻辣| 在线观看久久久久久| 国产精品久久久久久久久久尿| 欧美中文在线免费| 国产精品久久久久91| 国产在线98福利播放视频| 色噜噜亚洲精品中文字幕| 91精品视频免费看| 九九精品在线播放| 国产精品自产拍高潮在线观看| 色av中文字幕一区| 日韩欧美在线中文字幕| 91国产精品视频在线| 日韩免费在线观看视频| 清纯唯美亚洲综合| 亚洲色图狂野欧美| 欧美日韩免费一区| 亚洲人a成www在线影院| 亚洲国产女人aaa毛片在线| 欧美性感美女h网站在线观看免费| 日本久久中文字幕| 91中文字幕一区| 日韩在线免费观看视频| 国产精品亚洲激情| 国产精品主播视频| 成人免费淫片视频软件| 国产精品亚发布| 一本大道久久加勒比香蕉| 欧美最顶级丰满的aⅴ艳星| 中文字幕日韩精品在线观看| 日韩中文在线视频| 色婷婷综合成人av| 日韩最新免费不卡| 在线亚洲午夜片av大片| 国产午夜精品视频免费不卡69堂| 一道本无吗dⅴd在线播放一区| 欧美精品videofree1080p| 日韩精品在线免费播放| 国产小视频91| 国产精品视频导航| 国产精品久久久久77777| 91精品国产91久久久久| 久久精品电影一区二区| 亚洲美女在线观看| 欧美激情视频一区二区| 国产日韩欧美成人| 两个人的视频www国产精品| 欧美激情奇米色| 高清欧美性猛交xxxx黑人猛交| 97视频在线观看亚洲| 中文字幕精品一区久久久久| 亚洲人成电影在线播放| 欧美性猛交xxxx富婆| 91精品国产九九九久久久亚洲| 久久久久久久999| 欧美最猛黑人xxxx黑人猛叫黄| 久久精品视频播放| 久久久久久久久久久av| 97精品国产91久久久久久| 96pao国产成视频永久免费| 96pao国产成视频永久免费| 欧美一级大片在线免费观看| 美女啪啪无遮挡免费久久网站| 色无极亚洲影院| 亚洲精品97久久| 一夜七次郎国产精品亚洲| 久久av在线播放| 国产成人久久久精品一区| 国产精品免费一区二区三区都可以| 亚洲天堂av图片| 久久久久免费精品国产| 成人久久久久久| 日韩av在线资源| 亚洲自拍小视频| 狠狠躁天天躁日日躁欧美| 91久久久久久久久| 成人黄色生活片| 久久久久久久久久久免费精品| 国产91在线高潮白浆在线观看| 日韩有码在线观看| 国产成人自拍视频在线观看| 欧美多人爱爱视频网站| 韩国三级日本三级少妇99| 中文字幕日韩精品有码视频| 欧美国产在线电影| 78m国产成人精品视频| 久久久亚洲欧洲日产国码aⅴ| 2021国产精品视频| 国产精品扒开腿爽爽爽视频| 亚洲乱码一区二区| 热re99久久精品国产66热| 欧美极品少妇xxxxⅹ裸体艺术| 久久成人亚洲精品| 日韩中文综合网| 免费av一区二区| 亚洲第一男人av| 午夜精品久久久久久久白皮肤| 久久久久久久久电影| 久热精品视频在线观看一区| 性欧美xxxx视频在线观看| 日韩av手机在线| 97色伦亚洲国产| 日韩免费看的电影电视剧大全| 欧美视频在线观看 亚洲欧| 欧美极品欧美精品欧美视频| 亚洲亚裔videos黑人hd| 97超碰色婷婷| 懂色av影视一区二区三区| 欧美一级淫片aaaaaaa视频| 成人黄色激情网| 日韩激情在线视频| 精品日本美女福利在线观看| 国产一区二区三区三区在线观看| 欧美成年人在线观看| 777国产偷窥盗摄精品视频| 成人免费视频a| 国产精品久久久久久五月尺| 国产色综合天天综合网| 国产69精品99久久久久久宅男| 成人欧美一区二区三区黑人孕妇| 国产啪精品视频| 久久久www成人免费精品张筱雨| 一区二区三区四区在线观看视频|