iOS頭部漸變的表格視圖設計

iOS頭部漸變的表格視圖設計

        今天再來給你們帶來一個開發中經常使用到的視圖控制器,在不少應用中,可能都會遇到這樣的一個需求:表視圖控制器最上方有一個頭圖控件,當表格視圖滑動在頂部時,導航欄透明,當表格視圖逐漸向下滑動時,導航欄漸漸出現,而且在滑動期間,頭圖會展現相關的漸變更畫效果。之前常常會遇到這樣的需求,但從沒有整理與封裝完善,此次將其封裝成完整的控件,不管有無導航,均可以很好的支持,方便之後使用也提供給須要的朋友。數組

 


 

        在設計控件以前,咱們應該先編寫控件的頭文件,頭文件中將控件須要的屬性和方法列舉,以後再按定義好的接口一步步的來實現控件的編寫設計,這樣能夠結構清晰,而且不會顯得無從下手,控件的頭文件設計以下:app

//
//  YHBaseHeaderAnimatedViewController.h
//  YHBaseFoundationTest
//
//  Created by vip on 16/4/26.
//  Copyright © 2016年 jaki.zhang. All rights reserved.
/*
 *  這個視圖控制器建立出帶縮放頭圖效果的視圖控制器
 *  tip:
 *      1.這個視圖控制器若是是被導航push出來的 則內部會使用假導航進行漸隱模擬
 *      2.這個視圖控制器若是是被present出來的 則不會出現假導航欄
 *      3.這個視圖控制器中自帶一個TableView 設置TableView的頭圖不會影響原動畫效果
 *
 */

#import <UIKit/UIKit.h>
/**
 *  這個枚舉設置頭圖動畫滑動的速度等級
 */
typedef enum {
    YHBaseHeaderAnimatedLevelSlow,
    YHBaseHeaderAnimatedLevelNormal,
    YHBaseHeaderAnimatedLevelFast
}YHBaseHeaderAnimatedLevel;
@interface YHBaseHeaderAnimatedViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
@property(nonatomic,strong,readonly)UITableView * tableView;
/**
 *  設置動畫頭圖圖片
 */
@property(nonatomic,strong)UIView * animatedHeaderView;
/**
 *  設置TableView的頭視圖 
 *
 *  注意:設置tableView的頭視圖不可以在使用tableHeatherView方法 要使用這個屬性設置
 *
 */
@property(nonatomic,strong)UIView * tableHeaderView;
/**
 *  設置動畫頭圖高度
 *
 *  這個屬性若是不設置或者設置爲0 則默認會使用設置的image圖片比例
 *
 */
@property(nonatomic,assign)CGFloat headerHeight;
/**
 *
 *  設置動畫滑動速率
 */
@property(nonatomic,assign)YHBaseHeaderAnimatedLevel animatedlevel;
/**
 *
 *  設置頭圖可方法的最大scrollView偏移量 默認爲40
 *
 */
@property(nonatomic,assign)CGFloat maxScrollOffset;
/**
 *  設置是否帶漸隱效果
 *
 */
@property(nonatomic,assign)BOOL alphaAnimated;
/**
 *  設置最小漸變到的alpha漸隱值 <0 >1之間 默認爲0.5
 *
 */
@property(nonatomic,assign)CGFloat minAlpha;
/**
 *
 *  是否顯示毛玻璃模糊效果
 *
 */
@property(nonatomic,assign)BOOL bluerAnimated;
/**
 *
 *  設置最大小模糊度 默認爲1 
 *
 */
@property(nonatomic,assign)CGFloat maxBluer;
/**
 *  設置導航欄顏色 默認白色
 *
 */
@property(nonatomic,strong)UIColor * naviColor;
/**
 *  設置導航左側按鈕數組 若是不設置 會自動帶一個返回按鈕
 *
 */
@property(nonatomic,strong)NSArray * leftBarButtons;
/**
 *  設置導航左側按鈕數組 若是不設置 會自動帶一個返回按鈕
 *
 */
@property(nonatomic,strong)NSArray * rightBarButtons;
/**
 *  這個方法在修改了頭圖相關屬性後 須要調用刷新
 *
 *  注意:若是從新設置了TableView的tableheaderView屬性 也須要調用這個方法刷新
 *
 */
-(void)reloadAnimatedView;
@end

      在設計這個控件時,我主要考慮兩個須要優化的地方,第一是這個控制器在不一樣的場景下可能會有不一樣的結構,例如在導航結構中被push出來或者經過模態跳轉被present出來,我在這個控件的實現時作了兼容,實際上不管有無導航,控件內部都沒有使用系統的導航欄,而是模擬實現了一個自定義的導航欄來與系統的導航無縫銜接。優化

    .m文件中實現的代碼以下:動畫

#import "YHBaseHeaderAnimatedViewController.h"

@interface YHBaseHeaderAnimatedViewController ()
{
    //承載視圖
    UIView * _privteBGHeaderView;
    //寬高比例
    CGFloat _privteRate;
    //原始寬高
    CGFloat _privteOriWidth;
    CGFloat _privteOriHeught;
    UIVisualEffectView * _blurView;
    UINavigationBar * _naviBar;
}
@end

@implementation YHBaseHeaderAnimatedViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.edgesForExtendedLayout = UIRectEdgeNone;
    _tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
    [self.view addSubview:_tableView];
    _tableView.delegate=self;
    _tableView.dataSource=self;
     [self YHCreatView];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
//對導航進行處理
-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    if (self.navigationController) {
        [self.navigationController setNavigationBarHidden:YES animated:YES];
        [self showNavigationBar];
    }
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    if (self.navigationController) {
        [self.navigationController setNavigationBarHidden:NO animated:YES];
    }
}
-(void)showNavigationBar{
    if (_naviBar==nil) {
        _naviBar = [[UINavigationBar alloc]init];
        [self.view addSubview:_naviBar];
        _naviBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 64);
        [_naviBar setBackgroundImage:[UIImage imageNamed:@"clear"] forBarMetrics:UIBarMetricsDefault];
        [_naviBar setShadowImage:[UIImage imageNamed:@"clear"]];
        _naviBar.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0];
        UINavigationItem * item = [[UINavigationItem alloc]initWithTitle:self.title];
        _naviBar.items = @[item];
        item.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:self action:@selector(popToLast)];
    }
    if (self.animatedHeaderView==nil) {
        _naviBar.hidden=YES;
    }else{
        _naviBar.hidden=NO;
    }
}
-(void)popToLast{
    [self.navigationController popViewControllerAnimated:YES];
}
-(void)YHCreatView{
    if (self.maxScrollOffset==0) {
        self.maxScrollOffset=40;
    }
    if (self.minAlpha==0) {
        self.minAlpha = 0.5;
    }
    if (self.maxBluer==0) {
        self.maxBluer = 1;
    }
    _privteBGHeaderView = [[UIView alloc]init];
    _privteBGHeaderView.backgroundColor = [UIColor clearColor];
    self.tableView.backgroundColor = [UIColor clearColor];
    _blurView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
    [self reloadAnimatedView];
}

-(void)reloadAnimatedView{
    CGFloat viewH=0;
    CGFloat aniH=0;
    for (UIView * view in _privteBGHeaderView.subviews) {
        [view removeFromSuperview];
    }
    if (self.tableHeaderView) {
        viewH = viewH+self.tableHeaderView.bounds.size.height;
        [_privteBGHeaderView addSubview:self.tableHeaderView];
    }
    if (self.animatedHeaderView) {
        _privteRate = self.animatedHeaderView.frame.size.width/self.animatedHeaderView.frame.size.height;
        [self.animatedHeaderView addSubview:_blurView];
        _blurView.frame= self.animatedHeaderView.bounds;
        _blurView.alpha=0;
        _privteOriWidth = self.animatedHeaderView.frame.size.width;
        _privteOriHeught = self.animatedHeaderView.frame.size.height;
        if (self.headerHeight!=0) {
            viewH+=self.headerHeight;
            aniH = self.headerHeight;
        }else{
            viewH+=self.view.frame.size.width/self.animatedHeaderView.bounds.size.width*self.animatedHeaderView.frame.size.height;
            aniH = self.animatedHeaderView.bounds.size.height;
        }
        [self.view insertSubview:self.animatedHeaderView atIndex:0];
    }
    self.tableHeaderView.frame=CGRectMake(0, aniH, self.tableHeaderView.frame.size.width, self.tableHeaderView.frame.size.height);
    _privteBGHeaderView.frame=CGRectMake(0, 0, self.view.frame.size.width, viewH);
    self.tableView.tableHeaderView = _privteBGHeaderView;
}
-(void)setAnimatedHeaderView:(UIView *)animatedHeaderView{
    if (animatedHeaderView==nil) {
        if (_animatedHeaderView) {
            [_animatedHeaderView removeFromSuperview];
        }
    }
    _animatedHeaderView = animatedHeaderView;
    
}
-(void)setMinAlpha:(CGFloat)minAlpha{
    if (minAlpha<=0) {
        minAlpha=0.001;
    }
    if (minAlpha>=1) {
        minAlpha=0.999;
    }
    _minAlpha=minAlpha;
}
-(void)setMaxBluer:(CGFloat)maxBluer{
    if (maxBluer<=0) {
        maxBluer = 0.001;
    }
    if (maxBluer>=1) {
        maxBluer = 0.999;
    }
    _maxBluer = maxBluer;
}
-(void)setNaviColor:(UIColor *)naviColor{
    _naviColor = naviColor;
    _naviBar.backgroundColor = naviColor;
}
-(void)setLeftBarButtons:(NSArray *)leftBarButtons{
    _naviBar.topItem.leftBarButtonItems = leftBarButtons;
    _leftBarButtons = leftBarButtons;
}
-(void)setRightBarButtons:(NSArray *)rightBarButtons{
    _naviBar.topItem.rightBarButtonItems = rightBarButtons;
    _rightBarButtons = rightBarButtons;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if (self.animatedHeaderView==nil) {
        return;
    }
    if (self.tableView==scrollView) {
        //獲取到偏移量 默認兩倍
        CGFloat offset = scrollView.contentOffset.y*2;
        //若是小於0 則進行形變拉伸操做
        if (offset<=0) {
            
            if (offset<-self.maxScrollOffset*2) {
               
            }else{
                CGFloat height = _privteOriHeught+abs((int)offset);
                CGFloat width = height*_privteRate;
                self.animatedHeaderView.frame = CGRectMake(self.view.frame.size.width/2-width/2, offset/2, width, height);
            }
            if (_naviBar) {
                if (_naviBar.shadowImage==nil) {
                     [_naviBar setShadowImage:[UIImage imageNamed:@"clear"]];
                }
            }
        }else{
            //若是大於零 進行推出操做
            if (self.animatedlevel==YHBaseHeaderAnimatedLevelSlow) {
                //慢速
                self.animatedHeaderView.frame = CGRectMake(0, -offset/8, self.animatedHeaderView.frame.size.width, self.animatedHeaderView.frame.size.height);
            }else if(self.animatedlevel==YHBaseHeaderAnimatedLevelFast){
                //快速
                self.animatedHeaderView.frame = CGRectMake(0, -offset/2, self.animatedHeaderView.frame.size.width, self.animatedHeaderView.frame.size.height);
            }else{
                //正常
                self.animatedHeaderView.frame = CGRectMake(0, -offset/4, self.animatedHeaderView.frame.size.width, self.animatedHeaderView.frame.size.height);
            }
            //進行漸隱動畫處理
            CGFloat tmp = offset/2/_privteOriHeught;
            if (self.alphaAnimated) {
                self.animatedHeaderView.alpha = 1-(1-self.minAlpha)*tmp;
            }
            //進行模糊動畫
            if (self.bluerAnimated) {
                _blurView.alpha = self.maxBluer*tmp;
            }
            //進行導航顯示
            if (_naviBar) {
                _naviBar.backgroundColor = [_naviBar.backgroundColor colorWithAlphaComponent:tmp];
                if (_naviBar.shadowImage) {
                    [_naviBar setShadowImage:nil];
                }
                
            }
        }
        
       
    }
}
@end

    在使用時,建立一個視圖控制器繼承於它,在其viewDidLoad方法中進行一些簡單的設置便可,以下:atom

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //設置頭圖
    UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
    imageView.image = [UIImage imageNamed:@"image"];
    self.animatedHeaderView = imageView;
    //設置tableView的頭視圖
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)];
    label.backgroundColor = [UIColor purpleColor];
    label.textColor = [UIColor whiteColor];
    label.textAlignment =NSTextAlignmentCenter;
    label.text = @"下面進行功能演示";
    self.tableHeaderView = label;
    [self reloadAnimatedView];
}

    我寫了一個完整的演示Demo,Demo中有完整的功能演示,須要的朋友能夠自行下載:http://pan.baidu.com/s/1c1VKT00。spa

專一技術,熱愛生活,交流技術,也作朋友。設計

——琿少 QQ羣:203317592code

相關文章
相關標籤/搜索