Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ScrollView自動布局技巧

ScrollView自動布局技巧

編輯:關於Android編程

步驟:
1. sb中拖scrollView
2. 設置scrollView上下左右為0
4. 拖一個UIView"yellowView"到scrollView中(不是imageView)
5. 設置yellowView的自動布局上下左右為0(此時報錯,實際缺少尺寸"無法算出contentSize")
6. 設置yellowView和scrollView等寬等高
7. 更新frame,並運行
此時無法滾動,因為contentSize和scrollView的size一樣大
8.設置yellowView寬約束的是scrollView寬的2倍,並運行
此時 可以滾動了,因為yellowView的寬大於scrollView自身的寬
9. 設置yellowView頂部約束為64,並運行,會影響它的contentSize
10. 給yellowView上的添加按鈕,並設置約束,演示分頁屬性,並運行
實驗小結:
1. 設置scrollView中內容的距離scrollView四邊邊距值,會影響contentSize即滾動范圍,上下間距
   會影響contentSize的Hieght"垂直滾動范圍",左右間距會影響水平滾動范圍(不常用,了解裝逼使用)
2. 如果用AutoLayout約束scrollView中的內容時只設置四邊間距約束是不夠的,還要設置view寬高
3. 除了UIImageView可以不用直接設置寬高,因為它裡面如果設置了圖片,imageView的size會根據圖片               
   自適應,對應設置 scrollView的contentSize
4. 切記scrollView在實用自動布局時比較特殊
5. 建議:如果一個scrollView中有很多小控件可以把小控件添加一個容器視圖 view,設置容器view的尺
   寸為contentSize

scrollView-代理方法

scrollViewDidScroll: 滾動視圖滾動時使用 scrollViewDidEndDecelerating: 滾動視圖停止滾動時使用 viewForZoomingInScrollView: 縮放視圖時使用
滾動相關方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    NSLog(@"%@", @"scrollview視圖開始滾動");
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
    NSLog(@"%@", @"將要減速 - 在釋放開手之後調用");
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    NSLog(@"%@", @"完成減速 - 完全靜止後調用");
}
縮放相關方法

實現縮放的兩個步驟

需要設置最小縮放比例(minimumZoomScale)和最大縮放比例(maximumZoomScale)都為1時無法縮放 需要實現 “viewForZoomingInScrollView” 方法 告訴 scrollView 縮放的視圖

( 只要縮放就會調用 )

 // 告訴滾動視圖縮放的視圖
- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _imageView;
}


// @param scrollView 滾動視圖
// @param view       縮放的視圖
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view {

    NSLog(@"%@", @"縮放開始時調用");
}


/// @param scrollView 滾動視圖
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    NSLog(@"%@",@"正在縮放時調用");
}


/// @param scrollView 滾動視圖
/// @param view       縮放的視圖
/// @param scale      縮放的比例
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale {

    NSLog(@"%@",@" 縮放結束後調用");
}
拖拽相關方法
/// @param scrollView 滾動視圖
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    NSLog(@"%@", @"將要開始拖拽");
}


/// @param scrollView          滾動視圖
/// @param velocity            速度
/// @param targetContentOffset 目標偏移位置
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    NSLog(@"%@", @"將要結束拖拽");
}


/// @param scrollView 滾動視圖
/// @param decelerate 是否減速
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {

    NSLog(@"%@ %d", @"完成拖拽方法,手指放開後調用", decelerate);
    }
狀態欄相關方法
結合 self.scrollView.scrollsToTop = YES;使用要告訴它點了狀態欄對那個scrollView進行滾動
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {

    NSLog(@"%@", @"將要滾動到頂部,點擊狀態欄時調用");
    return YES;
}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView {

    NSLog(@"%@", @"已經滾動到狀態欄");
}
動畫相關方法
/**
 The scroll view calls this method at the end of its implementations of the setContentOffset:animated: and scrollRectToVisible:animated: methods, but only if animations are requested.

 滾動視圖會在實現了 setContentOffset:animated: & scrollRectToVisible:animated: 方法之後
 調用此方法

 同時必須在上述兩個方法中允許動畫
 */
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {

    NSLog(@"%@", @"調用動畫結束");
}

關於代理設計模式

自己想干一件事,但是自己不能主動完成/不能完成,要找一個對象幫自己完成

scrollView知道被滾動了,但是不知道被滾動以後將要做什麼

手寫代理步驟

找人做事情的人
協議 協議中的方法 代理對象屬性 在需要做事情的’時候’,通過代理對象,執行協議中的方法 做事情的人
遵守協議 設置代理對象 實現代理方法,在代理方法中做事情

ScrollView-屬性

contentSize: 內容大小,設置了才可以滾動 contentOffset: 內容偏移位置 contentInset: 內容間距 pagingEnabled: 是否允許分頁 bounces: 是否允許彈簧效果 showsHorizontalScrollIndicator: 是否允許顯示水平指示器(滾動條) showsVerticalScrollIndicator: 是否允許顯示垂直指示器(滾動條)
滾動內容屬性
// 內容偏移位置
@property(nonatomic)         CGPoint                      contentOffset;                  // default CGPointZero
// 內容大小,設置了才可以滾動
@property(nonatomic)         CGSize                       contentSize;                    // default CGSizeZero
// 內容間距
@property(nonatomic)         UIEdgeInsets                 contentInset;
委托屬性
@property(nullable,nonatomic,weak) id   delegate;
要想監聽滾動視圖的滾動 / 拖拽 / 縮放 / 狀態欄交互

需要設置 delegate
實現相關協議方法
彈簧效果屬性
// 允許彈簧效果
@property(nonatomic)   BOOL   bounces;                        // default YES. if YES, bounces past edge of content and back again
// 始終允許垂直彈
@property(nonatomic)   BOOL   alwaysBounceVertical;           // default NO. if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically
// 始終允許水平彈
@property(nonatomic)   BOOL   alwaysBounceHorizontal;
分頁屬性
// 允許分頁
@property(nonatomic,getter=isPagingEnabled) BOOL pagingEnabled __TVOS_PROHIBITED;// default NO. if YES, stop on multiples of view bounds
指示器屬性
// 顯示水平指示器
@property(nonatomic)         BOOL                         showsHorizontalScrollIndicator; // default YES. show indicator while we are tracking. fades out after tracking
// 顯示垂直指示器
@property(nonatomic)         BOOL                         showsVerticalScrollIndicator;   // default YES. show indicator while we are tracking. fades out after tracking
// 指示器間距
@property(nonatomic)         UIEdgeInsets                 scrollIndicatorInsets;          // default is UIEdgeInsetsZero. adjust indicators inside of insets
// 指示器樣式
@property(nonatomic)         UIScrollViewIndicatorStyle   indicatorStyle;                 // default is UIScrollViewIndicatorStyleDefault
在 scrollView 中指示器本質上就是 UIImageView

通過查看視圖層次結構可以看到
縮放屬性
// 最小縮放比例
@property(nonatomic) CGFloat minimumZoomScale;     // default is 1.0
// 最大縮放比例
@property(nonatomic) CGFloat maximumZoomScale;     // default is 1.0. must be > minimum zoom scale to enable zooming
要允許縮放

必須設置以上兩個屬性
同時遵守協議
實現協議方法 -viewForZoomingInScrollView:
狀態欄屬性
// 點擊狀態欄滾動到頂部
// default is YES. TVOS上此屬性禁用,
@property(nonatomic) BOOL  scrollsToTop __TVOS_PROHIBITED;          
一個視圖中,如果有多個 scrollView
只有唯一一個 scrollView 的 scrollsToTop 屬性設置為 YES,才支持點擊狀態欄滾動到頂部
雖然此屬性默認值即為YES不過還要要設置,不然不知道點了狀態欄要對那個scrollView進行滾動
鍵盤屬性
// 鍵盤解除模式
@property(nonatomic) UIScrollViewKeyboardDismissMode keyboardDismissMode NS_AVAILABLE_IOS(7_0); // default is UIScrollViewKeyboardDismissModeNone
如果是 UITextView,通常需要將 alwaysBounceVertical 屬性設置為 YES

typedef NS_ENUM(NSInteger, UIScrollViewKeyboardDismissMode) {
    // 無
    UIScrollViewKeyboardDismissModeNone,
    // 拖拽關閉鍵盤
    UIScrollViewKeyboardDismissModeOnDrag,      // dismisses the keyboard when a drag begins
    // 必須要拖拽到鍵盤才可以關閉鍵盤,很少使用
    UIScrollViewKeyboardDismissModeInteractive, // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss
} NS_ENUM_AVAILABLE_IOS(7_0);
常用方法
// 動畫設置偏移位置
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;  // animate at constant velocity to new offset

// 動畫設置滾動區域
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;         // scroll so rect is just visible (nearest edges). nothing if rect completely visible
三種圖像填充模式
- scale的意思是:縮放,在contentMode中出現的話,就是要改變圖形的大小了。
- aspect的意思是縱橫的比例,在contentMode中的意思是保持圖形的縱橫比,保持圖片不變形。

scale to fill:縮放圖片,使圖片充滿容器。因為沒有aspect,所以是不保持縱橫比的。圖片不是按比例縮放的。
scale aspect fit: 在保持縱橫比(aspect)的前提下,縮放圖片(scale),使圖片在容器內都顯示出來(fit)。
    保證圖片完整顯示,但不保證能充滿容器。
scale aspect fill:在保持縱橫比(aspect)的前提下,縮放圖片(scale),使圖片充滿容器(fill)。保證圖片能
    充滿容器,不保證圖片能完整顯示。

新特性視圖規則

新特性視圖

自動布局的選擇?
如果是全屏的直接bounds,如果不是考慮使用自動布局 並不是每次都需要現實新特性界面,所以留個後路,以後再改 創建控件時調用init或initWithFrame方法最後都會去調用對象父類的initWithFrame方法

隱藏狀態欄

隱藏狀態來這些不屬於顯示也不屬於數據,所以應該再C中找. -(BOOL)prefersStatusBarHidden

傳遞數據思路對比

View直接寫數據?(1) 控制器傳遞給View?(2) 可能面臨到視圖移植的問題,也就說,如果我另外一個項目也需要同樣的需求,那麼:
如果使用第一種方式,需要做的工作.
拷貝文件,更改view內部中的圖片名稱. 如果使用第二種方式,需要做的工作.
拷貝文件,在控制器重新寫數據,傳入view. 視圖只負責現實,控制器負責調度. 兩種方式,沒有對不對,只有合不合適.

將新特性數組傳遞給新特性

新建一個裝滿imageName的數組傳遞給視圖

設置scrollView的frame

創建scrollView並設置frame
ZFBGuideView *guideView = [[ZFBGuideView alloc] initWithFrame:self.view.bounds];
ZFBGuideView *guideView = [[ZFBGuideView alloc] init];
guideView.frame = self.view.bounds;
兩種寫法都會調用initWithFrame 重寫了initWithFrame並且同時重寫了init的方法,第一種形式的方法不會再調用init 設置子控件的frame應該使用layoutSubviews layoutSubviews一定要重寫父方法 約束的代碼不能寫在layoutSubviews方法中,此方法會多次調用

scrollView顯示圖片並設置屬性

setImageNames方法中添加imageView到scrollView中 並且設置圖像和contentSize 分頁 水平和垂直指示器(方便使用subviews) 禁用彈性

設置更多按鈕的自動布局

添加到imageView上 開啟用戶交互 userInteractionEnabled(bool)

添加按鈕監聽/新特性移除動畫

通過transform和透明度做動畫 移除整個新特性視圖

使用代碼創建pageControl

應該添加到新特性視圖上,如果添加到scrollView上會跟著滾動 禁用分頁的用戶交互

pageControl位置/設置總頁數

自動布局設置pageControl位置 總頁數應該根據圖片數量來,所以寫在setImageNames方法中

設置pageControl當前頁數

結束滾動的代理方法中,根據offset和scrollView的寬度進行計算 或者 在正在滾動的代理方法中,根據offset和scrollView的寬度進行計算(加0.4999再強轉)

拖拽細節/隱藏pageControl

需求的最右可以拖拽,思考怎麼樣增加? 根據頁數進行pageControl的隱藏和現實.
  1. 上一頁:
  2. 下一頁: