UIScrollView視覺差動畫

且行且珍惜_iOS發表於2018-12-06

前言:看到鳳凰新聞 頭條欄目的編輯推薦新聞是這個效果,覺得不錯,就想著實現一下,以下就是我的實現過程,示例程式碼請看這兒→UIScrollView視覺差動畫

總效果

一、首先實現一個基本的圖集瀏覽功能,如下圖

該功能太基礎,直接先貼一個UIScrollView,然後幾個UIImageView啪啪啪往UIScrollView上面一扔.......Over,不在此囉嗦咯。

普通的瀏覽效果.gif

二、分析動畫效果,提出解決方案

注意:這裡的left和right是區分拖動中可見的兩個檢視。

  • 1. 分析效果

由總效果圖和第一步的普通的瀏覽效果圖對比可以看出,在拖拽過程中,第一步中的普通效果圖是圖片之間首尾相連,當前(left)的圖片尾部連線下一個(right)的圖片首部;而目標總效果圖中的是圖片之間首首相連,尾尾相連,且滑動過程中,當前可見的圖片有漸進的裁剪效果;前者就像是平鋪在一起的一行書,一塊兒左右平移,而後者就像是翻書時看到的效果,當前頁***left***內容由邊到內逐漸消失,而下一頁***right***內容由邊緣到裡逐漸顯示。

  • 2. 解決思路

通過效果分析對比可知,我們需要在第一步的基礎上把每一個圖片檢視ImageView包裝在***WSLAnimationView***裡,讓WSLAnimationView去處理ImageView的動畫效果,那問題來了,我們怎麼處理呢?

  • 我們可以在拖拽過程中相對應的改變right/left圖片在父檢視WSLAnimationView上的X座標,把***right***圖片的座標位置放到***相對***於***left***圖片的**正下/偏右方位置,然後隨著拖拽滑動逐漸改變right以及left圖片的相對位置X座標,直至復位,回到它們在WSLAnimationView上的初始位置X=0,超出父檢視的部分裁剪掉,也是設定WSLAnimationView物件的clipsToBounds = YES。

思路示意圖.png

三、程式碼實現

  • 1. 首先建立一個承載UIImageView的容器WSLAnimationView,用於漸進動畫裁剪效果。
@interface WSLAnimationView ()
@property (nonatomic, strong) UIImageView * imageView;
/**
 imageView的橫座標 用於拖拽過程中的動畫
 */
@property (nonatomic, assign) CGFloat contentX;
@end

@implementation WSLAnimationView

- (instancetype)initWithFrame:(CGRect)frame{
    
    if (self = [super initWithFrame:frame]) {
        self.clipsToBounds = YES;
        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        [self addSubview:_imageView];
    }
    return self;
}
- (void)setContentX:(CGFloat)contentX{
    _contentX = contentX;
    _imageView.frame = CGRectMake(contentX, 0, self.frame.size.width, self.frame.size.height); 
}
複製程式碼
  • 2. 在拖拽滑動過程中進行動畫處理
#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define SCROLLVIEW_WIDTH SCREEN_WIDTH
#define BaseTag 10
/**
 動畫偏移量 是指rightView相對於leftView的偏移量
 */
#define AnimationOffset 100
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    
   CGFloat x = scrollView.contentOffset.x;
   NSInteger leftIndex = x/SCROLLVIEW_WIDTH;

   //這裡的left和right是區分拖動中可見的兩個檢視
    WSLAnimationView * leftView = [scrollView viewWithTag:(leftIndex + BaseTag)];
    WSLAnimationView * rightView = [scrollView viewWithTag:(leftIndex + 1 + BaseTag)];

    leftView.contentX = ((SCROLLVIEW_WIDTH - AnimationOffset) + (x - ((leftIndex + 1) * SCROLLVIEW_WIDTH))/SCROLLVIEW_WIDTH * (SCROLLVIEW_WIDTH - AnimationOffset));
    rightView.contentX = -(SCROLLVIEW_WIDTH - AnimationOffset) + (x - (leftIndex * SCROLLVIEW_WIDTH))/SCROLLVIEW_WIDTH * (SCROLLVIEW_WIDTH - AnimationOffset);
}
複製程式碼
  • 3. 程式碼處理邏輯說明

動畫偏移量AnimationOffset = 0 時 即***right***圖片的座標位置放到***相對***於***left***圖片的***正下方***位置,此時的效果如下圖所示;當AnimationOffset > 0 時就會出現目標總效果圖了。

AnimationOffset = 0時的效果圖

剛向左拖拽時的leftView和rightView檢視結構示意圖如下所示, 那麼拖拽中,逐漸移動復位rightView上的RightImage的X座標: rightView.contentX = 需要移動距離長度 - 移動百分比 * 需要移動距離長度 ; leftView.contentX 和這個類似,交由小夥伴們去思考。

需要移動距離長度 =  SCROLLVIEW_WIDTH - AnimationOffset;
移動百分比 = 拖拽距離 /  一頁寬度即螢幕寬度
拖拽距離 =   (偏移量X - leftView橫座標);
偏移量X = scrollView.contentOffset.x;
leftIndex = 偏移量X/SCROLLVIEW_WIDTH;
leftView橫座標 = leftIndex * SCROLLVIEW_WIDTH;
複製程式碼

剛向左拖拽時的結構示意圖

以上就是我實現這個效果的過程,示例程式碼請看這兒UIScrollView視覺差動畫;如果小夥伴們有其他的實現方法,歡迎再此留言交流??????

贊個.gif

如果需要跟我交流的話: ※ Github: github.com/wsl2ls ※ 個人部落格:wsl2ls.github.io ※ 簡書:www.jianshu.com/u/e15d1f644… ※ 微信公眾號:iOS2679114653 ※ QQ:1685527540

相關文章