有人能告诉我的执行方式UITableView
的展开/折叠动画sections
的UITableView
下面?
要么
您必须创建自己的自定义标题行,并将其作为每个部分的第一行.对UITableView
已经存在的标题进行子类化将会很痛苦.根据他们现在的工作方式,我不确定您是否可以轻松地采取行动.您可以将单元格设置为LOOK,如标题,并设置tableView:didSelectRowAtIndexPath
为手动展开或折叠它所在的部分.
我会存储一系列布尔值,这些布尔值对应于每个部分的"消耗"值.然后,您可以tableView:didSelectRowAtIndexPath
在每个自定义标题行上切换此值,然后重新加载该特定部分.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { ///it's the first row of any section so it would be your custom section header ///put in your code to toggle your boolean value here mybooleans[indexPath.section] = !mybooleans[indexPath.section]; ///reload this section [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade]; } }
然后设置numberOfRowsInSection
为检查mybooleans
值,如果未展开部分则返回1,如果展开部分,则返回1 +项目中的项目数.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (mybooleans[section]) { ///we want the number of people plus the header cell return [self numberOfPeopleInGroup:section] + 1; } else { ///we just want the header cell return 1; } }
此外,您还需要更新cellForRowAtIndexPath
以返回任何部分中第一行的自定义标题单元格.
Apple提供了一些使用表格视图部分标题动画展开/折叠动作的示例代码:Table View Animations and Gestures
这种方法的关键是实现- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
并返回一个自定义UIView,它包含一个按钮(通常与标题视图本身的大小相同).通过子类化UIView并将其用于标题视图(如此示例所示),您可以轻松存储其他数据,例如节号.
我得到了一个很好的解决方案,灵感来自Apple的Table View Animations和Gestures.我从Apple的样本中删除了不必要的部分并将其翻译成swift.
我知道答案很长,但所有代码都是必要的.幸运的是,您可以复制并覆盖大部分代码,只需要对步骤1和3进行一些修改即可
创造SectionHeaderView.swift
和SectionHeaderView.xib
import UIKit protocol SectionHeaderViewDelegate { func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int) func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionClosed: Int) } class SectionHeaderView: UITableViewHeaderFooterView { var section: Int? @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var disclosureButton: UIButton! @IBAction func toggleOpen() { self.toggleOpenWithUserAction(true) } var delegate: SectionHeaderViewDelegate? func toggleOpenWithUserAction(userAction: Bool) { self.disclosureButton.selected = !self.disclosureButton.selected if userAction { if self.disclosureButton.selected { self.delegate?.sectionHeaderView(self, sectionClosed: self.section!) } else { self.delegate?.sectionHeaderView(self, sectionOpened: self.section!) } } } override func awakeFromNib() { var tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "toggleOpen") self.addGestureRecognizer(tapGesture) // change the button image here, you can also set image via IB. self.disclosureButton.setImage(UIImage(named: "arrow_up"), forState: UIControlState.Selected) self.disclosureButton.setImage(UIImage(named: "arrow_down"), forState: UIControlState.Normal) } }
在SectionHeaderView.xib
(与灰色背景视图)应该是这个样子的实现代码如下(你可以根据自己的需要定制它,当然):
注意:
a)该toggleOpen
行动应与之相关联disclosureButton
二)disclosureButton
和toggleOpen
动作是没有必要的.如果您不需要按钮,可以删除这两件事.
2.创建 SectionInfo.swift
import UIKit class SectionInfo: NSObject { var open: Bool = true var itemsInSection: NSMutableArray = [] var sectionTitle: String? init(itemsInSection: NSMutableArray, sectionTitle: String) { self.itemsInSection = itemsInSection self.sectionTitle = sectionTitle } }
在你的桌面视图中
import UIKit class TableViewController: UITableViewController, SectionHeaderViewDelegate { let SectionHeaderViewIdentifier = "SectionHeaderViewIdentifier" var sectionInfoArray: NSMutableArray = [] override func viewDidLoad() { super.viewDidLoad() let sectionHeaderNib: UINib = UINib(nibName: "SectionHeaderView", bundle: nil) self.tableView.registerNib(sectionHeaderNib, forHeaderFooterViewReuseIdentifier: SectionHeaderViewIdentifier) // you can change section height based on your needs self.tableView.sectionHeaderHeight = 30 // You should set up your SectionInfo here var firstSection: SectionInfo = SectionInfo(itemsInSection: ["1"], sectionTitle: "firstSection") var secondSection: SectionInfo = SectionInfo(itemsInSection: ["2"], sectionTitle: "secondSection")) sectionInfoArray.addObjectsFromArray([firstSection, secondSection]) } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return sectionInfoArray.count } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if self.sectionInfoArray.count > 0 { var sectionInfo: SectionInfo = sectionInfoArray[section] as! SectionInfo if sectionInfo.open { return sectionInfo.open ? sectionInfo.itemsInSection.count : 0 } } return 0 } override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let sectionHeaderView: SectionHeaderView! = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier(SectionHeaderViewIdentifier) as! SectionHeaderView var sectionInfo: SectionInfo = sectionInfoArray[section] as! SectionInfo sectionHeaderView.titleLabel.text = sectionInfo.sectionTitle sectionHeaderView.section = section sectionHeaderView.delegate = self let backGroundView = UIView() // you can customize the background color of the header here backGroundView.backgroundColor = UIColor(red:0.89, green:0.89, blue:0.89, alpha:1) sectionHeaderView.backgroundView = backGroundView return sectionHeaderView } func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int) { var sectionInfo: SectionInfo = sectionInfoArray[sectionOpened] as! SectionInfo var countOfRowsToInsert = sectionInfo.itemsInSection.count sectionInfo.open = true var indexPathToInsert: NSMutableArray = NSMutableArray() for i in 0..0 { var indexPathToDelete: NSMutableArray = NSMutableArray() for i in 0..
4> jeantimex..:要在iOS中实现可折叠表部分,神奇的是如何控制每个部分的行数,或者我们可以管理每个部分的行高.
此外,我们需要自定义节标题,以便我们可以从标题区域(无论是按钮还是整个标题)监听点击事件.
如何处理标题?这很简单,我们扩展UITableViewCell类并制作一个自定义标题单元格,如下所示:
import UIKit class CollapsibleTableViewHeader: UITableViewCell { @IBOutlet var titleLabel: UILabel! @IBOutlet var toggleButton: UIButton! }然后使用viewForHeaderInSection挂接标题单元格:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = tableView.dequeueReusableCellWithIdentifier("header") as! CollapsibleTableViewHeader header.titleLabel.text = sections[section].name header.toggleButton.tag = section header.toggleButton.addTarget(self, action: #selector(CollapsibleTableViewController.toggleCollapse), forControlEvents: .TouchUpInside) header.toggleButton.rotate(sections[section].collapsed! ? 0.0 : CGFloat(M_PI_2)) return header.contentView }记住我们必须返回contentView,因为这个函数需要返回一个UIView.
现在让我们来处理可折叠部分,这里是切换每个部分的可折叠道具的切换功能:
func toggleCollapse(sender: UIButton) { let section = sender.tag let collapsed = sections[section].collapsed // Toggle collapse sections[section].collapsed = !collapsed // Reload section tableView.reloadSections(NSIndexSet(index: section), withRowAnimation: .Automatic) }取决于你如何管理部分数据,在这种情况下,我有这样的部分数据:
struct Section { var name: String! var items: [String]! var collapsed: Bool! init(name: String, items: [String]) { self.name = name self.items = items self.collapsed = false } } var sections = [Section]() sections = [ Section(name: "Mac", items: ["MacBook", "MacBook Air", "MacBook Pro", "iMac", "Mac Pro", "Mac mini", "Accessories", "OS X El Capitan"]), Section(name: "iPad", items: ["iPad Pro", "iPad Air 2", "iPad mini 4", "Accessories"]), Section(name: "iPhone", items: ["iPhone 6s", "iPhone 6", "iPhone SE", "Accessories"]) ]最后,我们需要做的是基于每个部分的可折叠道具,控制该部分的行数:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return (sections[section].collapsed!) ? 0 : sections[section].items.count }我在我的Github上有一个完整的演示程序:https://github.com/jeantimex/ios-swift-collapsible-table-section
如果你想在分组式表格中实现可折叠部分,我在这里有另一个带有源代码的演示:https://github.com/jeantimex/ios-swift-collapsible-table-section-in-grouped-section
希望有所帮助.
5> Son Nguyen..:我有一个更好的解决方案,您应该将UIButton添加到节标题中,并将此按钮的大小设置为等于节大小,但是将其隐藏为明确的背景颜色,之后您可以轻松检查单击哪个节点以展开或折叠
在我看来,这个解决方案比接受的答案要好,因为在语义上你将标题保留为标题,并且不使用假行来模拟标题.方法`tableView:numberOfRowsInSection:`将不受影响,您将继续能够将它用于它的真正含义.`tableView:cellForRowAtIndexPath:`也是如此.
6> RyanG..:我最后只是创建了一个包含一个按钮的headerView(事后我看到了Son Nguyen的解决方案,但是我的代码......看起来很多,但很简单):
为你的部分宣布一对bool
bool customerIsCollapsed = NO; bool siteIsCollapsed = NO;...码
现在在你的tableview委托方法中......
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _tblSearchResults.frame.size.width, 35)]; UILabel *lblSection = [UILabel new]; [lblSection setFrame:CGRectMake(0, 0, 300, 30)]; [lblSection setFont:[UIFont fontWithName:@"Helvetica-Bold" size:17]]; [lblSection setBackgroundColor:[UIColor clearColor]]; lblSection.alpha = 0.5; if(section == 0) { if(!customerIsCollapsed) [lblSection setText:@"Customers --touch to show--"]; else [lblSection setText:@"Customers --touch to hide--"]; } else { if(!siteIsCollapsed) [lblSection setText:@"Sites --touch to show--"]; else [lblSection setText:@"Sites --touch to hide--"]; } UIButton *btnCollapse = [UIButton buttonWithType:UIButtonTypeCustom]; [btnCollapse setFrame:CGRectMake(0, 0, _tblSearchResults.frame.size.width, 35)]; [btnCollapse setBackgroundColor:[UIColor clearColor]]; [btnCollapse addTarget:self action:@selector(touchedSection:) forControlEvents:UIControlEventTouchUpInside]; btnCollapse.tag = section; [headerView addSubview:lblSection]; [headerView addSubview:btnCollapse]; return headerView; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. if(section == 0) { if(customerIsCollapsed) return 0; else return _customerArray.count; } else if (section == 1) { if(siteIsCollapsed) return 0; else return _siteArray.count; } return 0; }最后触摸其中一个节标题按钮时调用的函数:
- (IBAction)touchedSection:(id)sender { UIButton *btnSection = (UIButton *)sender; if(btnSection.tag == 0) { NSLog(@"Touched Customers header"); if(!customerIsCollapsed) customerIsCollapsed = YES; else customerIsCollapsed = NO; } else if(btnSection.tag == 1) { NSLog(@"Touched Site header"); if(!siteIsCollapsed) siteIsCollapsed = YES; else siteIsCollapsed = NO; } [_tblSearchResults reloadData]; }
7> vamsi575kg..:这是我发现创建可扩展表视图单元格的最佳方法
.h文件
NSMutableIndexSet *expandedSections;.m文件
if (!expandedSections) { expandedSections = [[NSMutableIndexSet alloc] init]; } UITableView *masterTable = [[UITableView alloc] initWithFrame:CGRectMake(0,100,1024,648) style:UITableViewStyleGrouped]; masterTable.delegate = self; masterTable.dataSource = self; [self.view addSubview:masterTable];表视图委托方法
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section { // if (section>0) return YES; return YES; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if ([self tableView:tableView canCollapseSection:section]) { if ([expandedSections containsIndex:section]) { return 5; // return rows when expanded } return 1; // only top row showing } // Return the number of rows in the section. return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ; } // Configure the cell... if ([self tableView:tableView canCollapseSection:indexPath.section]) { if (!indexPath.row) { // first row cell.textLabel.text = @"Expandable"; // only top row showing if ([expandedSections containsIndex:indexPath.section]) { UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableContract"]]; cell.accessoryView = imView; } else { UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableExpand"]]; cell.accessoryView = imView; } } else { // all other rows if (indexPath.section == 0) { cell.textLabel.text = @"section one"; }else if (indexPath.section == 1) { cell.textLabel.text = @"section 2"; }else if (indexPath.section == 2) { cell.textLabel.text = @"3"; }else { cell.textLabel.text = @"some other sections"; } cell.accessoryView = nil; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } } else { cell.accessoryView = nil; cell.textLabel.text = @"Normal Cell"; } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if ([self tableView:tableView canCollapseSection:indexPath.section]) { if (!indexPath.row) { // only first row toggles exapand/collapse [tableView deselectRowAtIndexPath:indexPath animated:YES]; NSInteger section = indexPath.section; BOOL currentlyExpanded = [expandedSections containsIndex:section]; NSInteger rows; NSMutableArray *tmpArray = [NSMutableArray array]; if (currentlyExpanded) { rows = [self tableView:tableView numberOfRowsInSection:section]; [expandedSections removeIndex:section]; } else { [expandedSections addIndex:section]; rows = [self tableView:tableView numberOfRowsInSection:section]; } for (int i=1; i
您应该将问题标记为完全重复,而不是仅仅在所有问题上发送相同的答案.