今天公司的有一個需求是實現動態的 UITableView 頭部,基本需求是:git
下面先看看開源項目 ParallaxTableViewHeader 的實現方式,和本身的作個對比。github
它的虛化效果是經過 UIImage+ImageEffects 這個 category 實現的。app
具體內容就不深究了,對於圖像處理這塊的類庫不太熟悉。code
在 headerView 中能夠這樣使用獲取一張虛化的圖片:事件
- (void)refreshBlurViewForNewImage { UIImage *screenShot = [self screenShotOfView:self]; screenShot = [screenShot applyBlurWithRadius:5 tintColor:[UIColor colorWithWhite:0.6 alpha:0.2] saturationDeltaFactor:1.0 maskImage:nil]; self.bluredImageView.image = screenShot; }
源碼中提供了兩種工廠方法進行初始化:圖片
+ (id)parallaxHeaderViewWithImage:(UIImage *)image forSize:(CGSize)headerSize; + (id)parallaxHeaderViewWithSubView:(UIView *)subView;
第一種方法是經過 image 進行初始化,會調用默認的 init 方法,第二種是自定義 subView 的方法。ip
咱們只用看下默認的 init 方法:get
- (void)initialSetupForDefaultHeader { // 初始化一個 scrollView 做爲容器 UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; self.imageScrollView = scrollView; // 初始化默認大小的圖片,用於顯示 UIImageView *imageView = [[UIImageView alloc] initWithFrame:scrollView.bounds]; // 設置其拉伸模式爲:上下左右間距不變,拉伸高度和寬度。 imageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; // 設置圖片填充模式:儘可能填充,適當裁剪 imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.image = self.headerImage; self.imageView = imageView; [self.imageScrollView addSubview:imageView]; // 設置顯示的標籤文字 CGRect labelRect = self.imageScrollView.bounds; labelRect.origin.x = labelRect.origin.y = kLabelPaddingDist; labelRect.size.width = labelRect.size.width - 2 * kLabelPaddingDist; labelRect.size.height = labelRect.size.height - 2 * kLabelPaddingDist; UILabel *headerLabel = [[UILabel alloc] initWithFrame:labelRect]; headerLabel.textAlignment = NSTextAlignmentCenter; headerLabel.numberOfLines = 0; headerLabel.lineBreakMode = NSLineBreakByWordWrapping; headerLabel.autoresizingMask = imageView.autoresizingMask; headerLabel.textColor = [UIColor whiteColor]; headerLabel.font = [UIFont fontWithName:@"AvenirNextCondensed-Regular" size:23]; self.headerTitleLabel = headerLabel; [self.imageScrollView addSubview:self.headerTitleLabel]; // 設置虛化的圖片,默認 alpha 爲0,即徹底透明 self.bluredImageView = [[UIImageView alloc] initWithFrame:self.imageView.frame]; self.bluredImageView.autoresizingMask = self.imageView.autoresizingMask; self.bluredImageView.alpha = 0.0f; [self.imageScrollView addSubview:self.bluredImageView]; [self addSubview:self.imageScrollView]; }
大概瞭解了整個 view 的結構,不太清楚爲何要經過截屏的方式獲取圖片。源碼
經過實現 UISCrollViewDelegate
中的 scrollViewDidScroll
方法來監聽 UITableView 的滑動事件。it
若是當前 UITableView 滑動了,則會調用 headerView 的 layoutHeaderViewForScrollViewOffset
方法:
- (void)layoutHeaderViewForScrollViewOffset:(CGPoint)offset { CGRect frame = self.imageScrollView.frame; // 若是是上推 if (offset.y > 0) { frame.origin.y = offset.y *kParallaxDeltaFactor; self.imageScrollView.frame = frame; // 設置虛化圖層的 alpha 值。乘2是爲了增大虛化梯度 self.bluredImageView.alpha = 2 * (offset.y / kDefaultHeaderFrame.size.height) ; // 裁切 subview self.clipsToBounds = YES; } // 若是是下拉 else { CGFloat delta = 0.0f; CGRect rect = kDefaultHeaderFrame; delta = fabs(offset.y); // 爲了保持 header 的 top 對齊須要設置 y 座標 rect.origin.y -= delta; rect.size.height += delta; self.imageScrollView.frame = rect; self.clipsToBounds = NO; // 設置 label 的 alpha 值 self.headerTitleLabel.alpha = 1 - delta / kMaxTitleAlphaOffset; } }
上推的時候主要工做是虛化圖片,下拉的時候主要工做是設置圖片高度和座標。這個和我本身寫的基本思路相同。
大概就是這樣,引用中放了另外一個相似的項目供你們參考。這個項目與 Swift 無關,不過實現的思路能夠借鑑。