前言
本文為iOS自定義視圖封裝《一勞永逸》系列的第四期,旨在提供封裝思路徘禁,結(jié)果固然重要诅诱,但理解過程才最好。授人以魚不如授人以漁送朱,文章旨在幫助封裝程度較低的朋友們娘荡,大神可無視勿噴。
正文
最近更新項目需求驶沼,需要重構(gòu)導(dǎo)航選取模塊炮沐,故將封裝流程進(jìn)行分享,效果圖如下:
根據(jù)效果圖情況回怜,可知標(biāo)題欄位置需自定義大年,且選項位置等文字樣式可調(diào)節(jié),因此無法利用系統(tǒng)的UIActionSheet或UIAlertController進(jìn)行實(shí)現(xiàn)玉雾,需自定義視圖翔试,并考慮到適用場景,該ActionSheet后續(xù)會用于其他功能模塊中复旬,所以要封裝成通用類垦缅。
繼續(xù)分析需求,用什么控件作為主體會更好呢驹碍?沒錯壁涎,UITableView是在適合不過了,見刨析圖:
如上設(shè)計的優(yōu)勢在于可將自定義View傳入做為TableView的表頭視圖tableHeaderView志秃。對于選項位置若需定制其它樣式可自定義Cell進(jìn)行設(shè)置怔球。因此可滿足自定義ActionSheet的多種場景。
根據(jù)刨析圖洽损,首先我們分別創(chuàng)建maskView與主體TableView庞溜。這里需注意的是為了實(shí)現(xiàn)效果我們需要將TableView的顏色置為透明。
_tableView.backgroundColor = [UIColor clearColor];
并且我們要將TableView分為兩組,即主體選項與取消按鈕分離流码,因此設(shè)置代理方法:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (section == 0)?_optionsArr.count:1;
}
接下來進(jìn)行處理視圖的圓角效果又官。TableView主體做圓角效果這個不用多說,需要注意的是如何處理好TableViewCell的圓角形式漫试,若仍然簡單設(shè)置layer.cornerRadius會出現(xiàn)如下情況:
顯然很難看六敬,設(shè)計看到估計會崩潰,因此我們需要做的處理為僅為選項中的最后一項做圓角處理驾荣,即圖中的高德地圖選項外构,并且為了美觀效果,要達(dá)到只為其左下角與右下角做處理播掷。
這里我們需要借助UIBezierPath與CAShapeLayer進(jìn)行實(shí)現(xiàn)审编。判斷是否為最后選項,然后進(jìn)行如下設(shè)置歧匈。
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:
cell.contentView.bounds byRoundingCorners:
UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:
CGSizeMake(10, 10)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = cell.contentView.bounds;
maskLayer.path = maskPath.CGPath;
cell.layer.mask = maskLayer;
其中byRoundingCorners即為設(shè)置所需處理邊角參數(shù)垒酬。有如下枚舉克進(jìn)行選擇:
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
UIRectCornerTopLeft? ? = 1 << 0,
UIRectCornerTopRight? ? = 1 << 1,
UIRectCornerBottomLeft? = 1 << 2,
UIRectCornerBottomRight = 1 << 3,
UIRectCornerAllCorners? = ~0UL
};
比如將byRoundingCorners設(shè)置為UIRectCornerTopLeft| UIRectCornerBottomRight,即左上與右下設(shè)置件炉,View的效果為:
經(jīng)過上述調(diào)整勘究,視圖的圓角效果完成,最后設(shè)置組尾透明視圖即可:
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return SPACE;
}
- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, SPACE)];
footerView.backgroundColor = [UIColor clearColor];
return footerView;
}
做好如上處理后基本的UI效果即已完成斟冕。
接下來我們考慮外漏方法問題口糕,簡單模擬UIActionSheet的創(chuàng)建形式,公開方法:
- (instancetype)initWithTitleView:(UIView*)titleView
optionsArr:(NSArray*)optionsArr
cancelTitle:(NSString*)cancelTitle
selectedBlock:(void(^)(NSInteger))selectedBlock
cancelBlock:(void(^)())cancelBlock;
調(diào)用如下:
SureCustomActionSheet *optionsView = [[SureCustomActionSheet alloc]initWithTitleView:self.headView optionsArr:self.dataArr cancelTitle:@"取消" selectedBlock:^(NSInteger index) {
} cancelBlock:^{
}];
[self.view addSubview:optionsView];
這樣即可將所需頭視圖磕蛇、取消文字傳入景描,并處理選項事件等。
最后簡單給予視圖顯示與隱藏的效果秀撇,并在欠當(dāng)?shù)臅r機(jī)調(diào)用即可伏伯,且這里我們需要調(diào)節(jié)TableView的高度,使其適應(yīng)所包含內(nèi)容高度捌袜。
- (void)show {
_tableView.frame = CGRectMake(SPACE, Screen_height, Screen_Width - (SPACE * 2), _tableView.rowHeight * (_optionsArr.count + 1) + _headView.bounds.size.height + (SPACE * 2));
[UIView animateWithDuration:.5 animations:^{
CGRect rect = _tableView.frame;
rect.origin.y -= _tableView.bounds.size.height;
_tableView.frame = rect;
?}];
}
- (void)dismiss {
[UIView animateWithDuration:.5 animations:^{
CGRect rect = _tableView.frame;
rect.origin.y += _tableView.bounds.size.height;
_tableView.frame = rect;
} completion:^(BOOL finished) {
[self removeFromSuperview];
?}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {?
?? [self dismiss];
?}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event {
[self dismiss];
}
至此说搅,該需求效果已基本完成,如上摘取部分代碼虏等,demo已上傳github弄唧,需要可自行下載。