實(shí)現(xiàn)的效果如下

頁(yè)面很簡(jiǎn)單,4個(gè)按鈕、一張圖片、一個(gè) TableView 和一個(gè)半透明 View。
開(kāi)始擼代碼。
先來(lái)寫(xiě)按鈕
按鈕包含了一個(gè) UILabel 和一個(gè) UIImageView ,點(diǎn)擊的時(shí)候 UIImageView 翻轉(zhuǎn)。
先看 XYButton.h
#import <UIKit/UIKit.h>
@class XYButton;
typedef void(^ clickCityBtn_block_xyButton)(XYButton * view);
@interface XYButton : UIView
@property (nonatomic, strong)UILabel * titleLabel;
@property (nonatomic, strong)UIImageView * imageView;
- (void)setTitle:(NSString *)title;
/**
* 是否 是 顯示模式 YES 顯示
*/
@property (nonatomic, assign)BOOL isShow;
@property (nonatomic, copy)clickCityBtn_block_xyButton clickCityBtn_block_xyButton;
- (void)clickCityBtn_block_xyButton:(void(^)(XYButton * view))clickCityBtn_block_xyButton;
@end
block 用來(lái)進(jìn)行點(diǎn)擊后的回調(diào), isShow 用來(lái)標(biāo)記狀態(tài)。
點(diǎn)擊事件通過(guò) touchesEnded:withEvent: 來(lái)處理
- (void)touchesEnded
{
self.isShow = !self.isShow;
[UIView animateWithDuration:kHomeCityAnimate_time animations:^{
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI);
}];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self touchesEnded];
self.clickCityBtn_block_xyButton ? self.clickCityBtn_block_xyButton(self) : 0;
}
按鈕上面的字會(huì)有長(zhǎng)有短,為了好看,需要計(jì)算長(zhǎng)度進(jìn)行居中:
- (void)setTitle:(NSString *)title
{
self.titleLabel.text = title;
CGFloat width = [title boundingRectWithSize:CGSizeMake(222, 20)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:9]}
context:nil].size.width;
//圖片的寬度是12,所以label的寬度不能超過(guò) width - 12
width = (width > self.width - 12) ? (self.width - 12) : width;
self.titleLabel.width = width;
self.titleLabel.mj_x = self.width / 2 - (width + 12 + 2) / 2;
self.imageView.mj_x = CGRectGetMaxX(self.titleLabel.frame) + 2;
}
至此按鈕已經(jīng)完成
放4個(gè)按鈕的 View
為了方便控制,4個(gè)按鈕需要封裝到一個(gè) View 中。
照例先看 XYNearDriverSchoolSelectView.h
#import <UIKit/UIKit.h>
@class XYButton;
typedef void (^clickSelectView_block)(XYButton * btn);
@interface XYNearDriverSchoolSelectView : UIView
@property (nonatomic, copy)clickSelectView_block clickSelectView_block;
- (void)clickSelectView_blockWithBlock:(void(^)(XYButton * btn))clickSelectView_block;
@end
只有一個(gè) block 進(jìn)行按鈕被點(diǎn)擊后的回調(diào)。
截下來(lái)創(chuàng)建4個(gè)按鈕
NSInteger width = (NSInteger)((self.width - 3) / 4);
NSArray * titleArray = @[@"默認(rèn)排序", @"價(jià)格", @"距離", @"報(bào)名人數(shù)"];
WeakSelf(weakSelf);
for (int i = 0 ; i < titleArray.count ; i ++) {
XYButton * btn = [[XYButton alloc]
initWithFrame:CGRectMake((width + 1) * i, 1, width, self.height - 1)];
[btn setTitle:titleArray[i]];
btn.tag = 100000 + i;
[self addSubview:btn];
[btn clickCityBtn_block_xyButton:^(XYButton *view) {
weakSelf.clickSelectView_block ? weakSelf.clickSelectView_block(view) : 0 ;
}];
}
控制器
首先看屬性
@property (nonatomic, strong)XYNearDriverSchoolSelectView * selectView;
@property (nonatomic, strong)XYNearDriverSchoolSelectTableView * selectTableView;
/**
* 上一次點(diǎn)擊的 Btn
*/
@property (nonatomic, weak)XYButton * oldBtn;
/**
* 處于 顯示 模式的btn
*/
@property (nonatomic, weak)XYButton * showBtn;
然后是 ViewDidLoad
- (void)viewDidLoad {
self.view.backgroundColor = kDefaultBackgroudColor;
//這是頁(yè)面的內(nèi)容
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,
CGRectGetMaxY(self.selectView.frame) + 1,
kScreenWidth,
kScreenHeight - CGRectGetMaxY(self.selectView.frame) - 1 -kNavigationBar_Height)];
imageView.image = kImage(@"image");
imageView.backgroundColor = kWhiteColor;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
//半透明的 View
[self.view addSubview:self.selectTableView.backgroudView];
[self.selectTableView.backgroudView clickView:^(UIView *view) {
[self.showBtn touchesEnded:[NSSet set] withEvent:nil];
}];
//TableView
[self.view addSubview:self.selectTableView];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//放4個(gè)按鈕的 View
[self.view addSubview:self.selectView];
}
selectTableView 的初始化
- (XYNearDriverSchoolSelectTableView *)selectTableView
{
if (!_selectTableView) {
_selectTableView = [[XYNearDriverSchoolSelectTableView alloc]
initWithFrame:CGRectMake(0, 0, kScreenWidth, 1)];
/**
* 點(diǎn)擊cell 的回調(diào)
*/
[_selectTableView didSelectRowWithBlock:^(XYNearDriverSchoolSelectTableView
*tableView, NSIndexPath *indexPath) {
}];
}
return _selectTableView;
}
selectView 的初始化
不想看代碼的直接看下面
- (XYNearDriverSchoolSelectView *)selectView
{
if (!_selectView) {
_selectView = [[XYNearDriverSchoolSelectView alloc] initWithFrame:
CGRectMake(0, 0, kScreenWidth, 30)];
WeakSelf(weakSelf);
NSMutableArray * groupArray = @[].mutableCopy;
for (int i = 0 ; i < 4 ; i ++) {
NSMutableArray * array = @[].mutableCopy;
for (int i = 0 ; i < (arc4random()% 40) + 1; i ++) {
[array addObject:[NSString stringWithFormat:@"%d",(arc4random()% 40)]];
}
[groupArray addObject:array];
}
[_selectView clickSelectView_blockWithBlock:^(XYButton *btn) {
if (btn.isShow) {
NSLog(@" -- %@",btn.titleLabel.text);
self.showBtn = btn;
self.selectTableView.backgroudView.hidden = NO;
weakSelf.selectTableView.groupArray = groupArray[btn.tag - 100000];
}
if (self.oldBtn != btn && self.oldBtn.isShow) {
[self.oldBtn touchesEnded:[NSSet set] withEvent:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(kHomeCityAnimate_time / 2 * NSEC_PER_SEC)), dispatch_get_main_queue(),
^{
[weakSelf clickSelectViewWithBth:btn];
});
} else {
[weakSelf clickSelectViewWithBth:btn];
}
}];
}
return _selectView;
}
這里初始化完成 selectView 后,處理按鈕的點(diǎn)擊方法,4個(gè)按鈕對(duì)應(yīng)4個(gè)列表,我們這里只隨機(jī)4組字符串:
NSMutableArray * groupArray = @[].mutableCopy;
for (int i = 0 ; i < 4 ; i ++) {
NSMutableArray * array = @[].mutableCopy;
for (int i = 0 ; i < (arc4random()% 40) + 1; i ++) {
[array addObject:[NSString stringWithFormat:@"%d",(arc4random()% 40)]];
}
[groupArray addObject:array];
}
然后開(kāi)始處理點(diǎn)擊事件:
首先判斷按鈕的 isShow ,這里的獲取到的 isShow 是更新后的,因?yàn)樵诎粹o的 touchesEnded:withEvent: 先給 isShow 賦值,然后旋轉(zhuǎn) imageView 最后才進(jìn)行的回調(diào),所以 isShow 如果是 YES,那么就是處于下拉狀態(tài):
if (btn.isShow) {
NSLog(@" -- %@",btn.titleLabel.text);
self.showBtn = btn;
self.selectTableView.backgroudView.hidden = NO;
weakSelf.selectTableView.groupArray = groupArray[btn.tag - 100000];
}
在這里面給 self.showBtn 賦值,把黑色半透明View的hidden置為 NO,再通過(guò) tag 取到對(duì)應(yīng)的數(shù)據(jù)。
然后進(jìn)行判斷點(diǎn)擊的是否是同一個(gè)按鈕:
//如果點(diǎn)擊的不是同一個(gè)
if (self.oldBtn != btn && self.oldBtn.isShow) {
[self.oldBtn touchesEnded:[NSSet set] withEvent:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(kHomeCityAnimate_time / 2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[weakSelf clickSelectViewWithBth:btn];
});
} else {
[weakSelf clickSelectViewWithBth:btn];
}
如果點(diǎn)擊的不是同一個(gè)按鈕,那么先把 oldBtn 手動(dòng)點(diǎn)擊一下,讓 TableView 縮回去,然后在 kHomeCityAnimate_time / 2 秒之后調(diào)用 clickSelectViewWithBth:,如果點(diǎn)擊的同一個(gè)按鈕,直接調(diào)用 clickSelectViewWithBth:
再來(lái)說(shuō)說(shuō) clickSelectViewWithBth: 方法
- (void)clickSelectViewWithBth:(XYButton *)btn
{
NSInteger y = CGRectGetMaxY(self.selectView.frame) + 1;
if (!btn.isShow) {
y = - self.selectTableView.height;
}
[UIView animateWithDuration:kHomeCityAnimate_time animations:^{
self.selectTableView.mj_y = y;
}];
self.oldBtn = btn;
self.selectTableView.backgroudView.hidden = !self.showBtn.isShow;
}
依據(jù)按鈕的狀態(tài)來(lái)決定 TableView 的位置,每次完成后都把 oldBtn 指向該按鈕,然后
self.selectTableView.backgroudView.hidden = !self.showBtn.isShow;
是為了防止點(diǎn)擊了不同的按鈕的時(shí)候,上一個(gè)按鈕會(huì)把 TableView 往回縮,這時(shí)候黑色半透明View會(huì)消失,所以加入了一個(gè) showBtn ,就是當(dāng)前處于顯示狀態(tài)的按鈕,如果處于顯示狀態(tài)的按鈕的 isShow 為 NO,那么說(shuō)明所有按鈕都不在顯示狀態(tài),那么黑色半透明View應(yīng)該消失。
第一次寫(xiě)這樣的博客,寫(xiě)的有點(diǎn)亂,時(shí)間也有限,親們有哪里看不懂的可以留言