閑話
BrowsePictureViewController
顧名思義,這是一個關于圖片瀏覽的ViewController,這是項目中的一個圖片瀏覽器,我將他抽離出來,做成了第三方依賴~一來當當雷鋒,為開源事業做出一點貢獻(放屁這么多圖片瀏覽的開源庫誰來用你的?)二來我是個有代碼結構潔癖的人,項目寫的多了,項目目錄或者項目的代碼的耦合性一般都會不堪入目,于是就開始重構,其中,這個圖片瀏覽器就是我重構出來的東西。關于這個圖片瀏覽器,歡迎大家提出一些issue或者fork解決issue并提交pullrequest。
再隨便講講這個圖片瀏覽器的來源,最近在做的項目叫做“人言”(已經在Appstore上架,安卓應該也快要完成了),作為一個開發人員,我不對這個產品的性質或者趨勢做很多的評價,我只能說這個產品我覺得蠻好,而且會更好,要是有興趣的朋友也可以去下載看看(bug之類的事情還是會有的,各位手下留情,嘴下留情,給我們時間和建議,我們會做的更好,無論是信我還是信這個產品團隊)。
如果對這個產品的其他交互和UI功能點有需求,可以聯系我,我可以考慮適當開源,這也是我一直在做的事情。
正題
主要實現的功能有:
- 圖片瀏覽(多圖 && 單圖)
- 圖片保存
- 圖片添加水印 (可選)
- 大圖瀏覽的時候會有陀螺儀效果(類似于facebook paper圖片瀏覽效果)
接口的一些介紹
BrowsePictureViewController.h
+ (instancetype)create;
這是個創建接口,這個接口可以直接創建一個BrowsePictureViewController的對象
- (UIImageView *)currentImageView;
- (UIImageView *)currentOriginImageView;
- (void)showHideAllViews:(BOOL)show;
這三個接口可以無視,是提供給轉場動畫的。
@property (assign, nonatomic) BOOL scaleToMax;
這個屬性設置了在跳轉到圖片瀏覽的ViewController的時候是讓圖片填充滿全屏(scaleToMax == YES
),還是讓圖片可以完全顯示(scaleToMax == NO
),后者是微信圖片瀏覽的默認模式,而前者一般是微信圖片瀏覽事雙擊后的狀態
@property (assign, nonatomic) NSInteger startPage;
這個屬性設置了進入圖片瀏覽器的時候的起始照片的下標
以上兩個屬性都需要在create
調用之后設置,并都含有默認值,scaleToMax
的默認值為NO
,startPage
的默認值是0
BrowsePictureViewControllerDelegate
- (NSInteger)numberOfImagesInBrowsePictureViewController:(BrowsePictureViewController *)browsePitureViewController;
這個delegate返回這個圖片瀏覽器一共顯示的圖片張數,可選,如果沒有實現這個方法,則默認為1張。
- (NSString *)browsePictureViewController:(BrowsePictureViewController *)browsePictureViewController textAtIndex:(NSInteger)index;
這個代理返回水印文字,如果沒有實現或者返回nil這不添加水印(關于水印是一個需求,沒有該需求的使用者可以不實現這個delegate)
- (void)browsePictureViewController:(BrowsePictureViewController *)browsePictureViewController downLoadImage:(ImageDownLoadFinish)downLoadImage index:(NSInteger)Index;
這個代理給出一個downLoadImage
的Block對象,其作用是讓業務層能夠下載這個index的圖片并通過調用downLoadImage(image, index)
的方法返回一個image
我覺得這是一個我很多圖片瀏覽器不一樣的地方,其他的圖片瀏覽器一般都會向你索要一個url,然后會在自己內部通過自己實現的HTTP
請求下載一個圖片或者通過SDWebImage
之類的庫來實現一個下載圖片的邏輯,我覺得這個不是很好,首先,各個App的實現圖片下載的方法不一樣,在圖片瀏覽器內部實現如果和這個App的其他方法不同的話,感覺很多代碼就重復了,沒什么意思,然后我們遇到的很坑爹的問題就是類似使用OSS圖片存儲一般一個url都會有過期時間,所以當url過期的時候每個App一定會有各自不同的圖片下載邏輯,因此,我覺得圖片下載是一個和業務相關的東西,可以放到外面實現,而不應該在內部實現,這么想來美中不足的就是我使用了一個代理待實現外部下載圖片,其實我應該使用一種全局的,設置起來更加方便的方式實現外部下載圖片,這是個值得思考的問題,有機會需要再寫一下。
- (void)browsePictureViewControllerDidFinishSaving:(BrowsePictureViewController *)browsePictureViewController;
這個方法通知外部圖片瀏覽器已經保存了圖片
- (UIImageView *)browsePictureViewController:(BrowsePictureViewController *)browsePictureViewController imageViewAtIndex:(NSInteger)index;
這個代理返回通過一個下表index
返回一個UIImageView
的對象,這個對象就是當前在瀏覽的圖片的在外部的原始圖片
BrowsePictureCustomConfig
@interface BrowsePictureCustomConfig : NSObject
@property (strong, nonatomic) UIImage *waterMarkImge;
@property (strong, nonatomic) NSString *saveString;
+ (instancetype)sharedConfig;
這個類主要產生一個單例,設置一些屬性比如水印的圖片,保存按鈕的文字(主要用于國際化字符串)
UINavigationController (BrowsePictureViewController)
@interface UINavigationController (BrowsePictureViewController)
- (void)pushBrowsePictureViewController:(BrowsePictureViewController *)browsePictureViewController;
@end
正對這個ViewController提供一個PushViewController的方法
幾個技術點
關于切換動畫
切換動畫我主要使用了pop,總之最近可能算是迷上這個動畫引擎庫了,警告據我所知,這個動畫引擎配合UIKit的組件還是會有點問題的,可能會需要和AsyncDisplayKit一起服用效果更佳,關于pop的使用可能在之后會寫一篇介紹,不過這些文章真的滿大街都是,也就不想贅述了。
可能大多數的胸弟在使用pop的時候都回去使用它自帶的那些屬性動畫,不過我覺得自己寫屬性來做動畫會更佳炫酷,比如我的過場動畫里面就設置了一個transitionProgress
的屬性,然后在這個屬性的set方法中重寫一點更具這個屬性做出界面變換的代碼,當我將這個屬性的get&set做成屬性的動畫的時候,在使用popanimation來控制進度,就能輕松的完成一個組合動畫了。具體代碼我這邊粘貼一些:
- (void)setTransitionProgress:(CGFloat)transitionProgress {
_transitionProgress = transitionProgress;
animationView.frame = [ImageViewApearTransition rectWithProgress:transitionProgress startRect:[self fromFrame] toRect:[self toFrame]];
animationView.layer.cornerRadius = [ImageViewApearTransition valueWithProgress:transitionProgress startValue:originImageView.layer.cornerRadius toValue:0];
}
- (POPAnimatableProperty *)springAnimationProperty {
POPAnimatableProperty *springAnimationProperty = [POPAnimatableProperty propertyWithName:kPOPIMAGEVIEW_APEAR_PROPERTY initializer:^(POPMutableAnimatableProperty *prop) {
prop.readBlock = ^(id obj, CGFloat values[]) {
values[0] = [obj transitionProgress];
};
prop.writeBlock = ^(id obj, const CGFloat values[]) {
[obj setTransitionProgress:values[0]];
};
prop.threshold = 0.01;
}];
return springAnimationProperty;
}
圖片的縮放
這里使用scrollView開經行圖片的縮放,這里有點要注意的就是,我是使用xib來布局的,這邊不能使用autolayout,要使用原始的autoresize,然后在由于多圖片是使用UICollectionView來實現的,所以有愛有坑爹的重用會讓你很痛苦,在每次更新Cell的圖片的時候,一定千萬記住要重新設置ScollView的zoom值,這個真的非常重要!
水印 && 陀螺儀
這個主要看代碼就好了,陀螺儀如果要看起來相對動的比較柔和的話,需要在每次更新圖片位置的時候動畫的方式來調用,而不是直接修改
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseOut animations:^{
[_scrollView setContentOffset:CGPointMake(_previousValue, 0) animated:NO];
} completion:nil];
});