【Demo】UITableView实现分组可折叠下拉列表
来源:互联网 发布:淘宝联盟高佣金多少 编辑:程序博客网 时间:2024/06/05 02:31
前言
UITableView作为UIKit中最重要的一个组件,应用还是很广泛很灵活的,它的特性用来实现分组列表再合适不过。可折叠分组列表最典型的是好友列表,是一个二级目录,点击每一个分组都会展开或折叠一个好友列表。
这里使用TableView的section header作为分组一级目录,每个section的cell作为二级目录。section header里面放的是一个自定义的UIButton,button的图片设置为折叠指示箭头,button的文字为分组名称,为这个button定义代理,点击按钮时通知刷新对应的section的数据即可展开或者折叠该分组。
自定义section header头部按钮以及协议
头部按钮的制作主要有三点:一个是定义点击后的通知代理,二是调整按钮图片和文字的frame成左图右文字的样式(通过contentRect代理回调来调整),三是点击后按钮图片的旋转动画(tranform旋转90)。
//// SectionHeaderView.h// JXHDemo//// Created by 919575700@qq.com on 10/23/15.// Copyright (c) 2015 Jiangxh. All rights reserved.// section头部视图,是一个buntton#import <UIKit/UIKit.h>@class SectionHeaderView;/** * 自定义协议 */@protocol SectionHeaderDelegate <NSObject>//点击了section header- (void)sectionDidClicked:(SectionHeaderView *)sender;@end@interface SectionHeaderView : UIButton/** * 记录是否已经展开 */@property (nonatomic)BOOL isOpen;/** * 协议 */@property (nonatomic, weak) id<SectionHeaderDelegate>delegate;@end
//// SectionHeaderView.m// JXHDemo//// Created by 919575700@qq.com on 10/23/15.// Copyright (c) 2015 Jiangxh. All rights reserved.//#define sectionMargin 10#define sectionIconSize 20#import "SectionHeaderView.h"@interface SectionHeaderView()@end@implementation SectionHeaderView- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //设置按钮属性 [self setButton]; } return self;}/** * 设置按钮属性 */- (void)setButton { _isOpen = NO; //背景色 self.backgroundColor = [UIColor whiteColor]; // 文字颜色 [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // 添加指示图片 [self setImage:[UIImage imageNamed:@"arrow"] forState:UIControlStateNormal]; // 图片模式 self.imageView.contentMode = UIViewContentModeScaleAspectFit; // 添加下分割线 UIImageView *underLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.frame.size.height-1, self.frame.size.width, 1)]; // 贴图 [underLine setImage:[UIImage imageNamed:@"line"]]; //改变线的透明度 [underLine setAlpha:0.3]; [self addSubview:underLine]; // 添加点击事件 [self addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];}/** * 点击 */- (void)clicked:(SectionHeaderView *)sender { // 如果没展开,顺时针旋转90度 if (!_isOpen) { [sender.imageView setTransform:CGAffineTransformMakeRotation(M_PI_2)]; } // 如果展开了,逆时针旋转90度 else { [sender.imageView setTransform:CGAffineTransformMakeRotation(-M_PI_2)]; } // 通知代理 [_delegate sectionDidClicked:sender]; // 状态取反 _isOpen = !_isOpen;}/** * 返回代理需要的标题尺寸和图片尺寸 */- (CGRect)titleRectForContentRect:(CGRect)contentRect { return CGRectMake(55, 0, contentRect.size.width, contentRect.size.height);}- (CGRect)imageRectForContentRect:(CGRect)contentRect { return CGRectMake(20, 5, contentRect.size.height-10, contentRect.size.height-10);}@end
自定义cell
cell的样式根据需要可以随便设计,这里设置一个最简单的:一个头像,一个名字。
//// AccountCell.h// JXHDemo//// Created by Xinhou Jiang on 3/11/16.// Copyright © 2016年 Jiangxh. All rights reserved.//#import <UIKit/UIKit.h>@interface AccountCell : UITableViewCell// 头像@property (nonatomic, strong) UIImageView *avatar;// 昵称@property (nonatomic, strong) UILabel *name;@end
//// AccountCell.m// JXHDemo//// Created by Xinhou Jiang on 3/11/16.// Copyright © 2016年 Jiangxh. All rights reserved.//#define cellH 40 // cell高度#define ApplicationW [UIScreen mainScreen].bounds.size.width // 屏幕宽度#import "AccountCell.h"@implementation AccountCell-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // 头像 _avatar = [[UIImageView alloc]initWithFrame:CGRectMake(5, 5, cellH-10, cellH-10)]; _avatar.layer.cornerRadius = (cellH-10)/2; [self.contentView addSubview:_avatar]; // 账号 _name = [[UILabel alloc]initWithFrame:CGRectMake(cellH, 0, ApplicationW - cellH, cellH)]; _name.font = [UIFont systemFontOfSize:12.0]; [self.contentView addSubview:_name]; } return self;}@end
数据模型
数据主要是section分组的一个数据数组和每个分组的cell数据数组,这里为了简单固定返回了一组死数据,具体有了数据源在request的函数内将数据对应接入即可。
/** * 记录section的展开状态 */@property (nonatomic, strong)NSMutableArray *isOpen;/** * 记录section的标题数组 */@property (nonatomic, strong)NSArray *titles;/** * 请求数据 */- (void)initValue { // 标题数组假数据 _titles = @[@"朋友", @"同学", @"家人", @"同事"]; // 初始化所有section都是折叠状态 _isOpen = [[NSMutableArray alloc] initWithCapacity:_titles.count]; for (int i = 0; i<_titles.count; i++) { [_isOpen addObject:@NO]; }}/** * cell */- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"identifier"; // 具体可以自制cell组件 AccountCell *cell = [[AccountCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; // 头像,具体应该从好友数据中取 [cell.avatar setImage:[UIImage imageNamed:@"male"]]; // 昵称,具体应该从好友数据中取 cell.name.text = @"夏明"; //cell颜色 //cell.backgroundColor = RGBColor(200, 200, 200); return cell;}
UITableView分组下拉列表
主体就是TableView的一个完整应用,包括section和cell的管理。
//// FolderTableViewController.h// JXHDemo//// Created by 919575700@qq.com on 10/23/15.// Copyright (c) 2015 Jiangxh. All rights reserved.// 可折叠section的表格#import <UIKit/UIKit.h>@interface FolderTableViewController : UITableViewController@end
//// FolderTableViewController.m// JXHDemo//// Created by 919575700@qq.com on 10/23/15.// Copyright (c) 2015 Jiangxh. All rights reserved.//#define sectionHeaderH 30 //组头部的高度#define ApplicationW [UIScreen mainScreen].bounds.size.width // 屏幕宽度#define RGBColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] // 通过RGB创建颜色#import "FolderTableViewController.h"#import "SectionHeaderView.h"#import "AccountCell.h"@interface FolderTableViewController ()<SectionHeaderDelegate>/** * 记录section的展开状态 */@property (nonatomic, strong)NSMutableArray *isOpen;/** * 记录section的标题数组 */@property (nonatomic, strong)NSArray *titles;@end@implementation FolderTableViewController- (void)viewDidLoad { [super viewDidLoad]; // 表格基本设置 self.title = @"可展开的TableView"; self.view.backgroundColor = RGBColor(240, 240, 240); // 清除底部多余cell [self.tableView setTableFooterView:[[UIView alloc] initWithFrame:CGRectZero]]; // 清除分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 请求数据 [self initValue];}/** * 请求数据 */- (void)initValue { // 标题数组假数据 _titles = @[@"朋友", @"同学", @"家人", @"同事"]; // 初始化所有section都是折叠状态 _isOpen = [[NSMutableArray alloc] initWithCapacity:_titles.count]; for (int i = 0; i<_titles.count; i++) { [_isOpen addObject:@NO]; }}#pragma mark - 组设置/** * 多少组 */- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return _titles.count;}/** * section header的高度 */- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return sectionHeaderH;}/** * section header的视图 */- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { // section头部视图 SectionHeaderView *sectionHeader = [[SectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, ApplicationW, sectionHeaderH)]; // 标题 [sectionHeader setTitle:[_titles objectAtIndex:section] forState:UIControlStateNormal]; // 为headerview打上tag [sectionHeader setTag:section]; // 代理 sectionHeader.delegate = self; return sectionHeader;}#pragma mark SectionHeader实现代理/** * 实现代理,sectionheader 点击 */- (void)sectionDidClicked:(SectionHeaderView *)sender { // 取反状态 BOOL reverse = ![_isOpen[sender.tag] boolValue]; _isOpen[sender.tag] = [NSNumber numberWithBool:reverse]; /*** 这里刷新后section的header也会被刷新,导致指示箭头又恢复到旋转之前的状态,待解决 ***/ // 刷新点击的分区(展开或折叠) [self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationNone];}#pragma mark - 组内行设置/** * 每组多少行 */- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if ([_isOpen[section] boolValue]) { return 5; // 具体应该返回该分组好友的个数 }else { return 0; }}/** * cell */- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"identifier"; // 具体可以自制cell组件 AccountCell *cell = [[AccountCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; // 头像,具体应该从好友数据中取 [cell.avatar setImage:[UIImage imageNamed:@"male"]]; // 昵称,具体应该从好友数据中取 cell.name.text = @"夏明"; //cell颜色 //cell.backgroundColor = RGBColor(200, 200, 200); return cell;}@end
组件的调用
组件的使用很简单,一句话加入,引入TavleViewController类,实例化为一个子viewcontroller即可。
- (void)viewDidLoad { [super viewDidLoad]; // 显示折叠视图 FolderTableViewController *foldableVC = [[FolderTableViewController alloc]init]; [self addChildViewController:foldableVC]; [self.view addSubview:foldableVC.view];}
存在的问题(待解决)
存在的一个问题是,点击分组按钮时,刷新的是整个section,包括头部的header按钮,因此虽然头部按钮点击后箭头旋转了,但由于马上被更新了换了新的头部按钮,导致箭头看上去没有反应,而TableView并没有只更新某个section的所有cell而不更新section的header的方法。暂时没有想到比较优雅的解决办法,探索中…orz
Demo下载(不想花积分的请回复邮箱)
http://download.csdn.net/detail/cordova/9673964
- 【Demo】UITableView实现分组可折叠下拉列表
- 实现可折叠的分组tableview
- IOS UITableView Section下拉列表实现
- RecyclerView分组列表的实现及demo
- 【Demo】IOS使用UItableView实现下拉菜单组件(UITableView的使用方法)
- 可折叠列表
- android:使用BaseExpandableListAdapter实现可折叠的列表
- [Android]BaseExpandableListAdapter实现可折叠的列表
- 使用BaseExpandableListAdapter实现可折叠的列表
- android:使用BaseExpandableListAdapter实现可折叠的列表
- iOS UITableView中的下拉列表
- Android UI设计: 仿QQ好友列表分组悬停,自定义Header,下拉刷新结合Demo
- android 仿QQ列表可折叠+自定义Dialog结合的DEMO
- 仿QQ分组列表(UITableView)
- UITableView分组列表,显示右侧索引
- recycleview实现分组列表
- 实现下拉更新UITableView EGORefreshTableHeaderView
- 实现下拉更新UITableView EGORefreshTableHeaderView
- 06-图1 列出连通集 (25分)
- 单向链表
- HelloDjango
- POJ2506 Tiling(递推+大数)
- 通过自定义.xml文件实现各种效果的SeekBar
- 【Demo】UITableView实现分组可折叠下拉列表
- 动态规划专题 01背包问题详解【转】
- hdu5965扫雷
- HDU-2818-Building Block
- ViewPager组件的使用
- C语言/C++|Bubble Sort(冒泡排序)
- python一行代码解决SyntaxError: Non-ASCII character '\xe4'
- spring框架基于注解aop的通知
- PHP的错误和异常处理