前言:對于每天逛【簡書】的伙伴應該會發(fā)現(xiàn)窿侈,簡書App的UI比較清爽磷醋、舒服冕臭。個人比較喜歡余蟹,這也是本人從CSDN的入門到現(xiàn)在的放棄(雖然自我感覺仍然在入門~)的原因卷胯。在看到【簡書】個人中心板塊的資料界面有頭像的縮放功能,之前在其他App上也看到這樣的效果威酒。處于好奇想自己動手實現(xiàn)一下(Demo地址, swift版本后提交)窑睁,自我學習^-^
效果展示~其余請忽視
實現(xiàn)思路
- 自定義控件內(nèi)部添加
UIImageView
控件 - 檢測外部控件滾動試圖的偏移量
contentOffset
進行縮放比例計算并控制 - 設置圖片事件代理, 處理點擊事件
- 將創(chuàng)建的視圖添加到
navigationBar
上面(當然也可以添加到titleView挺峡, titleView的位置是由導航欄決定的,所以不能完全把控),這里考慮到可以自定義其他位置担钮,所以添加到navigationBar
- 封裝控件提供自定義參數(shù)
1. 實現(xiàn)UIScrollViewDelegate
代理的scrollViewDidScroll
方法將scrollView
視圖傳遞給自定義視圖的zoomWithScroll
方法獲取偏移量contentOffset
// 傳遞scrollView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[_zoomView zoomWithScrollView:scrollView];
}
2. 通過contentOffset
偏移量計算縮放比例scale
/**
根據(jù)偏移量計算縮放比例
@param scrollView 滾動視圖
*/
- (void)zoomWithScrollView:(UIScrollView *)scrollView {
// 獲取偏移量
CGFloat offsetY = scrollView.contentOffset.y + scrollView.contentInset.top;
// 縮放比例
CGFloat scale = 1.0;
// 變化基數(shù)
CGFloat changeHeight = _scaleRate * self.frame.size.height;
if(offsetY > 0) { // 偏移量為正, 上拉縮小
scale = MAX(_minScale, 1-offsetY/changeHeight);
}else { // 偏移量為負, 下拉放大
scale = MIN(_maxScale, 1-offsetY/changeHeight);
}
// 形變變化
_imageView.transform = CGAffineTransformMakeScale(scale, scale);
// 固定頂部坐標, 保持不變
CGRect frame = _imageView.frame;
frame.origin.y = _imageTopMargin;
_imageView.frame = frame;
}
ps: 其中用到的有些成員變量參數(shù)都設置有默認值,方便根據(jù)需求設置, 具體含義后面統(tǒng)一說明~
3.定義協(xié)議MRScrollZoomViewDelegate
處理頭像點擊事件監(jiān)聽橱赠,這里需要在創(chuàng)建UIImageView
的時候開啟用戶響應以及添加點擊手勢,因為UIImageView
不同于UIButton
箫津,UIButton
繼承自UIControl
默認具有事件響應功能狭姨,而UIImageView
繼承自UIView
不具有,所以需要我們添加手勢響應事件
@protocol MRScrollZoomViewDelegate <NSObject>
@optional
- (void)zoomViewDidClick:(MRScrollZoomView *)zoomView;
@end
imageV.userInteractionEnabled = YES; // 開啟響應用戶能力
// 創(chuàng)建并添加點擊手勢
UITapGestureRecognizer *panGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewClick:)];
[_imageView addGestureRecognizer:panGes];
/**
點擊事件處理
*/
- (void)imageViewClick:(UIImageView *)imageView {
if([self.delegate respondsToSelector:@selector(zoomViewDidClick:)]) {
[self.delegate zoomViewDidClick:self];
}
}
3.計算縮放比例 (重點)
/**
根據(jù)偏移量計算縮放比例
@param scrollView 滾動視圖
*/
- (void)zoomWithScrollView:(UIScrollView *)scrollView {
// 獲取偏移量
CGFloat offsetY = scrollView.contentOffset.y + scrollView.contentInset.top;
// 縮放比例
CGFloat scale = 1.0;
// 變化基數(shù)
CGFloat changeHeight = _scaleRate * self.frame.size.height;
if(offsetY > 0) { // 偏移量為正, 上拉縮小
scale = MAX(_minScale, 1-offsetY/changeHeight);
}else { // 偏移量為負, 下拉放大
scale = MIN(_maxScale, 1-offsetY/changeHeight);
}
// 形變變化
_imageView.transform = CGAffineTransformMakeScale(scale, scale);
// 固定頂部坐標, 保持不變
CGRect frame = _imageView.frame;
frame.origin.y = _imageTopMargin;
_imageView.frame = frame;
}
其中的MAX(_minScale, 1-offsetY/changeHeight);
和MIN(_maxScale, 1-offsetY/changeHeight)
是用于根據(jù)偏移量控制最大、最小的縮放程度。_minScale
是默認的最小縮放比例為1.f拐云,_maxScale
是默認的最大縮放比例為1.f, 都是默認不縮放师抄。
提供的可修改屬性說明
/**
最大縮放比例 --- 默認值1.0(保持初始比例)
*/
@property (nonatomic, assign) CGFloat maxScale;
/**
最小縮放比例 --- 默認值1.0(保持初始比例)
*/
@property (nonatomic, assign) CGFloat minScale;
/**
頭像頂部固定間距 --- 默認值0
*/
@property (nonatomic, assign) CGFloat imageTopMargin;
/**
變化速率 --- 默認為3.0(偏移量/高度*速率), 越小越快
*/
@property (nonatomic, assign) CGFloat scaleRate;
實現(xiàn)效果
Demo使用示例
- 拷貝文件夾
MRScrollZoomView
到工程中 - 引入
MRScrollZoomView.h
- 創(chuàng)建視圖
MRScrollZoomView
并設置相關(guān)屬性
MRScrollZoomView *zoomView = [[MRScrollZoomView alloc] init];
zoomView.frame = CGRectMake(0, 0, 70, 70);
zoomView.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, 30);
zoomView.minScale = 0.5;
zoomView.maxScale = 1.35;
zoomView.imageTopMargin = 10;
zoomView.scaleRate = 3.0;
zoomView.delegate = self;
zoomView.imageView.image = [UIImage imageNamed:@"headIcon"];
[self.navigationController.navigationBar addSubview:zoomView];
```
- 實現(xiàn)代理方法
zoomViewScrollView:
可選
pragma mark - MRScrollZoomViewDelegate
- (void)zoomViewDidClick:(MRScrollZoomView *)zoomView {
NSLog(@"點擊圖片處理");
}