前言
之前项目为一个房产类项目,所以必不可少的需要一个新房、二手房、租房、中介门店的筛选控件,当然大多数项目可能新房、二手房、租房筛选就够了哈,不过多了个中介门店筛选倒不至于对筛选控件需求有多大影响,样式也都能复用的。所以就想着去找一个别人封装好的轮子直接拿来用了,奈何找来找去也没找到有合适的,无奈只能自己花些时间去封装一个了。项目完成了,当然筛选功能也是好的了,便打算整理一下开源出去了,也省的后面人用到了再造轮子了,毕竟能帮助更多人省些事自己也是开心的。奈何当初项目中筛选需求几经变更,方法定义过多,代码略显冗余了,使用起来实在不够简洁好用。趁着项目完结时间有些盈余,所以便就抽空结合自己项目和贝壳找房的筛选功能和样式,重新写了一份筛选控件好开源出来了。
支持
- 提供新房、二手房、租房的完整筛选功能实现
- 支持固定和列表sectionHead悬停下拉筛选两种模式
- 支持单列表、双列表、滑动列表、切换列表、列表输入等多种下拉筛选样式
- 展示样式支持自定义调节
- 展示数据支持自定义设置
预览
概述
总的来说实现这样一个房屋筛选控件倒不复杂,为了实现代码的简洁性,基本的实现就是数据源的构造、传参、UI构造及数据绑定、数据处理及回调这几个常用过程。下拉列表也是由UITableView根据数据参数进行的一个动态展示。这里便也不再多赘述内部实现了,只讲一下数据源的构造了,传参方式下面使用示例中会有提到。
- 数据构造
根据项目需求不同可能数据来源也有些区别,我们之前的项目中项筛选所需数据为接口请求所得,以此更好来实现后台动态配置,当然也是有缺陷的哈,就是每次需要接口请求后才能展示筛选。这里为了展示和实现筛选功能就把这些数据在本地写了,当然如果有其它筛选要求也可以在本地json中动态增加。这里是封装了一个FilterDataUtil类专门构造数据源,通过传入FilterType类型获取筛选数据源。如果有对数据源操作有需求可以在此类的方法实现中进行调整或修改。
/** 筛选类型 */
typedef NS_ENUM(NSUInteger, FilterType) {
FilterTypeIsNewHouse = 1, //新房
FilterTypeSecondHandHouse, //二手房
FilterTypeISRent, //租房
};
@interface FilterDataUtil : NSObject
/** 根据FilterType类型获取数据 */
- (NSMutableArray *)getTabDataByType:(FilterType)type;
@end
属性定义
为了实现筛选控件的通用性,所以开放以下属性和方法,方便外部更好的调节设置和调用。
@property (nonatomic, weak) id<ZHFilterMenuViewDelegate> zh_delegate;
@property (nonatomic, weak) id<ZHFilterMenuViewDetaSource> zh_dataSource;
@property (nonatomic, strong) NSMutableArray *filterDataArr; //传入数据源(必传)
@property (nonatomic, strong) NSArray<NSString *> *titleArr; //传入标题数据源(必传)
@property (nonatomic, strong) NSArray<NSString *> *imageNameArr; //传入折叠图片数据源(不传不展示图片)
@property (nonatomic, strong) NSArray<NSString *> *selectImageNameArr;//传入选择状态下的折叠图片数据源(不传默认取imageNameArr里的图片)
@property (nonatomic, strong) UIColor *titleColor; //菜单标题文本颜色(默认333333)
@property (nonatomic, strong) UIColor *titleSelectedColor; //菜单标题选择状态下的颜色(默认3072F5)
@property (nonatomic, strong) UIColor *lineColor; //菜单标题底部分割线颜色(默认e8e8e8)
@property (nonatomic, assign) CGFloat titleFontSize; //菜单标题字号(默认15)
@property (nonatomic, assign) BOOL showLine; //菜单标题底部分割线是否显示(默认YES)
@property (nonatomic, assign) BOOL titleLeft; //文字标题是否居左 不平分(默认NO)
@property (nonatomic, assign) BOOL lastTitleRight; //最后一个文字标题是否固定居右(默认NO,为YES的情况下tab标题宽度固定为60)
@property (nonatomic, assign) CGFloat listHeight; //选择列表的高度(默认44)
@property (nonatomic, assign) CGFloat bottomHeight; //列表底部的高度(默认80)
@property (nonatomic, assign) CGFloat itemTitleFontSize; //item标题字号大小(默认12)
@property (nonatomic, strong) UIColor *itemBGColor; //item背景颜色(默认f5f5f5)
@property (nonatomic, strong) UIColor *itemBGSelectedColor; //item选择时背景颜色(默认eef6ff)
@property (nonatomic, assign) CGFloat space; //item间隔(默认15)
@property (nonatomic, assign) CGFloat itemHeight; //item高(默认30)
@property (nonatomic, assign) NSInteger lineNum; //一行展示数量(默认4,当内容字符数大于7时lineNum = 2)
@property (nonatomic, assign) NSInteger maxLength; //输入框最大文本数量(默认7位)
@property (nonatomic, strong) NSMutableArray *buttonArr;//菜单tab标题button数据
/** 快速初始化
* maxHeight:下拉列表最大展示高度
*/
- (instancetype)initWithFrame:(CGRect)frame maxHeight:(CGFloat)maxHeight;
/** 参数传完后开始调用以显示 */
- (void)beginShowMenuView;
/** 外部快捷调用展开菜单列表 */
- (void)menuTappedWithIndex:(NSInteger)tapIndex;
/** 菜单列表消失 */
- (void)hideMenuList;
使用示例
注意:为了方便展示演示,这里代码使用示例是新房、二手房、租房筛选功能整合在一起的。如果需要分开的,和根据自身情况根据相应类型做下拆分即可。
- 初始化
- (ZHFilterMenuView *)menuView
{
if (!_menuView) {
_menuView = [[ZHFilterMenuView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 45) maxHeight:CGRectGetHeight(self.view.frame) - 45];
_menuView.zh_delegate = self;
_menuView.zh_dataSource = self;
if (self.filterType == FilterTypeIsNewHouse) {
_menuView.titleArr = @[@"区域",@"价格",@"户型",@"更多",@"排序"];
_menuView.imageNameArr = @[@"x_arrow",@"x_arrow",@"x_arrow",@"x_arrow",@"x_arrow"];
} else if (self.filterType == FilterTypeSecondHandHouse) {
_menuView.titleArr = @[@"区域",@"价格",@"房型",@"更多",@"排序"];
_menuView.imageNameArr = @[@"x_arrow",@"x_arrow",@"x_arrow",@"x_arrow",@"x_arrow"];
} else if (self.filterType == FilterTypeISRent) {
_menuView.titleArr = @[@"位置",@"方式",@"租金",@"更多",@""];
_menuView.imageNameArr = @[@"x_arrow",@"x_arrow",@"x_arrow",@"x_arrow",@"x_px"];
}
[self.view addSubview:_menuView];
}
return _menuView;
}
- 传参并开始显示
这里根据FilterDataUtil类通过传入FilterType类型获取筛选数据源传参即可。
//便于演示房源展示数据源暂时是写在本地,可根据自身情况,如果需从接口请求可自行做下调整
FilterDataUtil *dataUtil = [[FilterDataUtil alloc] init];
self.menuView.filterDataArr = [dataUtil getTabDataByType:self.filterType];
//开始显示
[self.menuView beginShowMenuView];
这里传入展示类型,以此控制每种情况下的展示类型和确定类型。
/** 返回每个 tabIndex 下的确定类型 */
- (ZHFilterMenuConfirmType)menuView:(ZHFilterMenuView *)menuView confirmTypeInTabIndex:(NSInteger)tabIndex
{
if (tabIndex == 4) {
return ZHFilterMenuConfirmTypeSpeedConfirm;
}
return ZHFilterMenuConfirmTypeBottomConfirm;
}
/** 返回每个 tabIndex 下的下拉展示类型 */
- (ZHFilterMenuDownType)menuView:(ZHFilterMenuView *)menuView downTypeInTabIndex:(NSInteger)tabIndex
{
if (tabIndex == 0) {
return ZHFilterMenuDownTypeTwoLists;
} else if (tabIndex == 1) {
if (self.filterType == FilterTypeISRent) {
return ZHFilterMenuDownTypeOnlyItem;
} else {
return ZHFilterMenuDownTypeItemInput;
}
} else if (tabIndex == 2) {
if (self.filterType == FilterTypeISRent) {
return ZHFilterMenuDownTypeItemInput;
} else {
return ZHFilterMenuDownTypeOnlyItem;
}
} else if (tabIndex == 3) {
return ZHFilterMenuDownTypeOnlyItem;
} else if (tabIndex == 4) {
return ZHFilterMenuDownTypeOnlyList;
}
return ZHFilterMenuDownTypeOnlyList;
}
- 回调
/** 确定回调 */
- (void)menuView:(ZHFilterMenuView *)menuView didSelectConfirmAtSelectedModelArr:(NSArray *)selectedModelArr
{
NSArray *dictArr = [ZHFilterItemModel mj_keyValuesArrayWithObjectArray:selectedModelArr];
NSLog(@"结果回调:%@",dictArr.mj_JSONString);
}
/** 警告回调(用于错误提示) */
- (void)menuView:(ZHFilterMenuView *)menuView wangType:(ZHFilterMenuViewWangType)wangType
{
if (wangType == ZHFilterMenuViewWangTypeInput) {
NSLog(@"请输入正确的价格区间!");
}
}
经过重新封装之后控件方法调用和使用要简洁了很多,也更加通用性。但是也有可能会有些遗漏或问题,如果使用中遇到问题或者有更好的意见建议也欢迎提出。
下载地址
ZHFilterMenuView,如果感觉对你有所帮助的话记得给个star喽!