Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/121.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS中UITableView中的下拉列表_Ios_Objective C_Swift_Uitableview_Dropdown - Fatal编程技术网

iOS中UITableView中的下拉列表

iOS中UITableView中的下拉列表,ios,objective-c,swift,uitableview,dropdown,Ios,Objective C,Swift,Uitableview,Dropdown,如何在iOS中创建这种类型的tableview??? 在这里,若我们点击第一行“Account”,那个么它会自动滚动显示更多的行,如图所示。 如果我们再次点击帐户,则该视图将被隐藏。通常我通过设置行高来实现。例如,您有两个带有下拉列表的菜单项: 菜单1 项目1.1 项目1.2 项目1.3 菜单2 项目2.1 项目2.2 因此,您必须创建一个包含两个部分的表视图。第一部分包含4行(菜单1及其项),第二部分包含3行(菜单2及其项) 始终仅为节中的第一行设置高度。如果用户单击第一行,您可以

如何在iOS中创建这种类型的tableview???

在这里,若我们点击第一行“Account”,那个么它会自动滚动显示更多的行,如图所示。
如果我们再次点击帐户,则该视图将被隐藏。

通常我通过设置行高来实现。例如,您有两个带有下拉列表的菜单项:

  • 菜单1
    • 项目1.1
    • 项目1.2
    • 项目1.3
  • 菜单2
    • 项目2.1
    • 项目2.2
因此,您必须创建一个包含两个部分的表视图。第一部分包含4行(菜单1及其项),第二部分包含3行(菜单2及其项)


始终仅为节中的第一行设置高度。如果用户单击第一行,您可以通过设置高度来展开此部分行并重新加载此部分。

如果您不喜欢使用任何外部库,则可以创建2个自定义单元格。一个在展开前显示,另一个在展开后显示(具有不同的标识符)。单击单元格时,检查单元格是否展开。如果不是,则使用扩展单元标识符,否则使用非扩展单元标识符


这是创建扩展表视图单元格的最佳且干净的方法。

简单的方法是使用UITableView节头作为单元格->并将行数设置为0,将节数设置为折叠和扩展状态

  • 。这是TableViewSection标题,isExpand->section.count else 返回0

    -正常细胞

    -正常细胞

    -正常细胞

  • 。这是TableViewSection标题,isExpand->section.count else 返回0

    -正常细胞

    -正常细胞

    -正常细胞


您需要一个可折叠的表视图。为了实现这一点,在TableView中,必须跟踪哪些部分被折叠(收缩)以及哪些部分被展开。为此,您需要维护一组展开的节的索引,或者一个布尔数组,其中每个索引的值指示是否展开了相应的节。为特定行指定高度时,检查特定索引处的值。查看更多帮助

您可以了解截面表视图

Github上提供了第三方库,可以将您从hustel中解救出来。看看
或者,

您可以将Account作为一个单元格,点击后展开,显示三个按钮(“配置文件”、“激活帐户”、“更改密码”),但这会产生一个问题:点击三个按钮中的每一个按钮将计为“用户选择的帐户单元格”并触发
-tableView:didSelectRowAtIndexPath:
,从而展开/折叠单元格

或者,您可以将每个隐藏选项(“配置文件”、“激活帐户”、“更改密码”)设置为单独的表视图单元格。但我不知道如何将这三个单元格作为一个整体来设置动画(而不是分别从零高度扩展到完全扩展)

因此,也许最好的解决方案是:

  • 具有偶数单元格(索引:0、2、4…)以实现“菜单标题”和“切换菜单打开/关闭”的作用(指向下面描述的相关奇数单元格)
  • 在奇数索引(1、3、5…)中,交错(最初折叠的)“菜单体”单元格,每个单元格的每个选项都有一个按钮(例如,“配置文件”、“激活帐户”、“更改密码”)。使用目标操作响应用户选择的每个选项/按钮
  • 实现table view委托方法,以便仅可选择偶数单元格(菜单标题),并实现选择逻辑以展开/折叠相应的奇数单元格(内部-tableView:DidSelectRowatineXpath:)。例如,选择索引0(“帐户”)处的单元格会导致展开/折叠索引1处的单元格(菜单选项为“配置文件”、“激活帐户”、“更改密码”)

  • 这不是UITableView最优雅的用法,但可以完成这项工作。

    您可以轻松地将单元格设置为标题,并设置
    表格视图:didselectRowatinexPath
    以手动展开或折叠它所在的部分。
    如果我存储一个与“expended”对应的布尔数组每个部分的值。然后,您可以让每个自定义标题行上的
    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];
        }
    }
    
    然后设置数字
    numberofrowsinssection
    以检查
    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;
        }
    }
    
    您还必须更新
    单元格for行索引路径
    ,以返回任何
    中第一行的自定义标题单元格

    -(UIView*)tableView:(UITableView*)tableView view for headerinsection:(NSInteger)section
    是提供“自己的自定义标题”的更好方法,因为这正是它的设计目的

    有关更多详细信息,请参阅此或此

    此外,您还可以使用
    setIndentationLevel
    获取这种类型的表视图。请参考此示例。我认为这是下拉表视图的最佳解决方案

    如果您想制作一个简单的标题和单元格下拉列表,请参阅


    希望,这就是你要找的。如有任何问题,请与我联系。:)

    通过表视图单元格实现此功能的最简单、最自然的方法。没有展开的单元格视图,没有节标题,没有简单的单元格(毕竟我们是在一个表视图中)

    设计如下:

    • 使用MVVM方法,创建一个包含配置单元格所需信息的
      CollapsableViewModel
      类:标签、图像
    • 除上述字段外,还有两个额外字段:
      子字段
      ,whi
      objc_getAssociatedObject.
      
      UITapGestureRecognizer *singleTapRecogniser = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureHandler:)] autorelease];
      [singleTapRecogniser setDelegate:self];
      singleTapRecogniser.numberOfTouchesRequired = 1;
      singleTapRecogniser.numberOfTapsRequired = 1;   
      [sectionHeaderView addGestureRecognizer:singleTapRecogniser];
      
      class ClsMenuGroup: NSObject {
      
          // We can also add Menu group's name and other details here.
          var isSelected:Bool = false
          var arrMenus:[ClsMenu]!
      }
      
      class ClsMenu: NSObject {
      
          var strMenuTitle:String!
          var strImageNameSuffix:String!
          var objSelector:Selector!   // This is the selector method which will be called when this menu is selected.
          var isSelected:Bool = false
      
          init(pstrTitle:String, pstrImageName:String, pactionMehod:Selector) {
      
              strMenuTitle = pstrTitle
              strImageNameSuffix = pstrImageName
              objSelector = pactionMehod
          }
      }
      
       class YourViewController: UIViewController, UITableViewDelegate {
      
          @IBOutlet var tblMenu: UITableView!
          var objTableDataSource:HDTableDataSource!
          var arrMenuGroups:[AnyObject]!
      
          // MARK: - View Lifecycle
      
          override func viewDidLoad() {
              super.viewDidLoad()
              if arrMenuGroups == nil {
                  arrMenuGroups = Array()
              }
      
              let objMenuGroup = ClsMenuGroup()
              objMenuGroup.arrMenus = Array()
      
              var objMenu = ClsMenu(pstrTitle: "Manu1", pstrImageName: "Manu1.png", pactionMehod: "menuAction1")
              objMenuGroup.arrMenus.append(objMenu)
      
              objMenu = ClsMenu(pstrTitle: "Menu2", pstrImageName: "Menu2.png", pactionMehod: "menuAction2")
              objMenuGroup.arrMenus.append(objMenu)
      
              arrMenuGroups.append(objMenuGroup)
              configureTable()
          }
      
      
          func configureTable(){
      
              objTableDataSource = HDTableDataSource(items: nil, cellIdentifier: "SideMenuCell", configureCellBlock: { (cell, item, indexPath) -> Void in
      
                  let objTmpGroup = self.arrMenuGroups[indexPath.section] as! ClsMenuGroup
                  let objTmpMenu = objTmpGroup.arrMenus[indexPath.row]
                  let objCell:YourCell = cell as! YourCell
      
                  objCell.configureCell(objTmpMenu)  // This method sets the IBOutlets of cell in YourCell.m file.
              })
      
              objTableDataSource.sectionItemBlock = {(objSection:AnyObject!) -> [AnyObject]! in
      
                  let objMenuGroup = objSection as! ClsMenuGroup
                  return (objMenuGroup.isSelected == true) ? objMenuGroup.arrMenus : 0
              }
      
              objTableDataSource.arrSections = self.arrMenuGroups
              tblMenu.dataSource = objTableDataSource
              tblMenu.reloadData()
          }
      
          // MARK: - Tableview Delegate
      
          func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
      
              let objTmpGroup = self.arrMenuGroups[indexPath.section] as! ClsMenuGroup
              let objTmpMenu = objTmpGroup.arrMenus[indexPath.row]
      
              if objTmpMenu.objSelector != nil && self.respondsToSelector(objTmpMenu.objSelector) == true {
                  self.performSelector(objTmpMenu.objSelector)  // Call the method for the selected menu.
              }
      
              tableView.reloadData()
          }
      
          func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
      
              let arrViews:[AnyObject] = NSBundle.mainBundle().loadNibNamed("YourCustomSectionView", owner: self, options: nil)
              let objHeaderView = arrViews[0] as! UIView
              objHeaderView.sectionToggleBlock = {(objSection:AnyObject!) -> Void in
      
                  let objMenuGroup = objSection as! ClsMenuGroup
                  objMenuGroup.isSelected = !objMenuGroup.isSelected
                  tableView.reloadData()
              }
              return objHeaderView
          }
      
          // MARK: - Menu methods
      
          func menuAction1(){
      
          }
      
          func menuAction2(){
      
          }
      }
      
      @interface TestTableViewController ()
      {
          BOOL showMenu;
      }
      
      @implementation TestTableViewController
      
      - (void)viewDidLoad {
          [super viewDidLoad];
      
          // Uncomment the following line to preserve selection between presentations.
          // self.clearsSelectionOnViewWillAppear = NO;
      
          // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
          // self.navigationItem.rightBarButtonItem = self.editButtonItem;
          [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"accountMenu"];
          [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"accountSubMenu"];
      }
      
      #pragma mark - Table view data source
      
      - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
          return 2;
      }
      
      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
          if (section == 0) {
              // Account Menu
              return 1;
          }
          if (showMenu) {
              // Profile/Private Account/Change Password
              return 3;
          }
          // Hidden Account Menu
          return 0;
      }
      
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          UITableViewCell *cell;
      
          if (indexPath.section == 0) {
              cell = [tableView dequeueReusableCellWithIdentifier:@"accountMenu" forIndexPath:indexPath];
              cell.textLabel.text = @"Account";
          }
          else
          {
              cell = [tableView dequeueReusableCellWithIdentifier:@"accountSubMenu" forIndexPath:indexPath];
              switch (indexPath.row) {
                  case 0:
                      cell.textLabel.text = @"Profile";
                      break;
                  case 1:
                      cell.textLabel.text = @"Private Account";
                      break;
                  case 2:
                      cell.textLabel.text = @"Change Password";
                      break;
      
                  default:
                      break;
              }
          }
      
      
          return cell;
      }
      
      -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
      {
          if (indexPath.section == 0) {
              // Click on Account Menu
              showMenu = !showMenu;
              [tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
          }
      }
      
      class DataObject
      {
          let name : String
          let imageURL : NSURL?
          private(set) var children : [DataObject]
      
          init(name : String, imageURL : NSURL?, children: [DataObject]) {
              self.name = name
              self.imageURL = imageURL
              self.children = children
          }
      
          convenience init(name : String) {
              self.init(name: name, imageURL: nil, children: [DataObject]())
          }
      }
      
      protocol TreeTableViewCell {
          func setup(withTitle title: String, imageURL: NSURL?, isExpanded: Bool)
      }
      
      class ChildTreeTableViewCell : UITableViewCell, TreeTableViewCell {
          func setup(withTitle title: String, imageURL: NSURL?, isExpanded: Bool) {
             //implementation goes here 
          }
      }
      
      class RootTreeTableViewCell : UITableViewCell, TreeTableViewCell {
          func setup(withTitle title: String, imageURL: NSURL?, isExpanded: Bool) {
             //implementation goes here
          }
      }
      
      let profileDataObject = DataObject(name: "Profile")
      let privateAccountDataObject = DataObject(name: "Private Account")
      let changePasswordDataObject = DataObject(name: "Change Password")
      let accountDataObject = DataObject(name: "Account", imageURL: NSURL(string: "AccountImage"), children: [profileDataObject, privateAccountDataObject, changePasswordDataObject])
      
      let groupDataObject = DataObject(name: "Group", imageURL: NSURL(string: "GroupImage"), children: [])
      let eventDataObject = DataObject(name: "Event", imageURL: NSURL(string: "EventImage"), children: [])
      let dealsDataObject = DataObject(name: "Deals", imageURL: NSURL(string: "DealsImage"), children: [])
      
      data = [accountDataObject, groupDataObject, eventDataObject, dealsDataObject]
      
      func treeView(treeView: RATreeView, numberOfChildrenOfItem item: AnyObject?) -> Int {
          if let item = item as? DataObject {
              return item.children.count //return number of children of specified item
          } else {
              return self.data.count //return number of top level items here
          }
      }
      
      func treeView(treeView: RATreeView, child index: Int, ofItem item: AnyObject?) -> AnyObject {
          if let item = item as? DataObject {
              return item.children[index] //we return child of specified item here (using provided `index` variable)
          } else {
              return data[index] as AnyObject //we return root item here (using provided `index` variable)
          }
      }
      
      func treeView(treeView: RATreeView, cellForItem item: AnyObject?) -> UITableViewCell {
          let cellIdentifier = item ? “TreeTableViewChildCell” : “TreeTableViewCellRootCell”
          let cell = treeView.dequeueReusableCellWithIdentifier(cellIdentifier) as! TreeTableViewCell
      
          //TreeTableViewCell is a protocol which is implemented by two kinds of
          //cells - the one responsible for root items in the tree view and another 
          //one responsible for children. As we use protocol we don't care
          //which one is truly being used here. Both of them can be
          //configured using data from `DataItem` object.
      
          let item = item as! DataObject
          let isExpanded = treeView.isCellForItemExpanded(item) //this variable can be used to adjust look of the cell by determining whether cell is expanded or not
      
          cell.setup(withTitle: item.name, imageURL: item.imageURL, expanded: isExpanded)
      
          return cell
      }
      
      protocol CellDescriptor: class {
          var count: Int { get }
          var identifier: String! { get }
      }
      
      extension CellDescriptor {
          var count: Int { return 1 }
      }
      
      protocol ExpandableCellDescriptor: CellDescriptor {
          var active: Bool { get set }
          var children: [CellDescriptor] { get set }
      
          subscript(index: Int) -> CellDescriptor? { get }
          func indexOf(cellDescriptor: CellDescriptor) -> Int?
      }
      
      extension ExpandableCellDescriptor {
          var count: Int {
              var total = 1
              if active {
                  children.forEach({ total += $0.count })
              }
              return total
          }
      
          var countIfActive: Int {
              ...
          }
      
          subscript(index: Int) -> CellDescriptor? {
              ...
          }
      
          func indexOf(cellDescriptor: CellDescriptor) -> Int? {
              ...
          }
      
          func append(cellDescriptor: CellDescriptor) {
              children.append(cellDescriptor)
          }
      }
      
      class ExpandableOption: ExpandableCellDescriptor {
      
          var delegate: ExpandableCellDelegate?
      
          var identifier: String!
          var active: Bool = false {
              didSet {
                  delegate?.expandableCell(self, didChangeActive: active)
              }
          }
      
          var children: [CellDescriptor] = []
          var title: String?
      }
      
      class SwitchTableViewCell: UITableViewCell, CellDescrptionConfigurable {
      
          @IBOutlet weak var titleLabel: UILabel!
          @IBOutlet weak var switchControl: UISwitch!
      
          var cellDescription: CellDescriptor! {
              didSet {
                  if let option = cellDescription as? ExpandableOption {
                      titleLabel.text = option.title
                      switchControl.on = option.active
                  }
              }
          }
      
          @IBAction func activeChanged(sender: UISwitch) {
             let expandableCellDescriptor = cellDescription as! ExpandableCellDescriptor
             expandableCellDescriptor.active = sender.on
          }
      }
      
      var options = CellDescriptionArray()
      
      override func viewDidLoad() {
         super.viewDidLoad()
      
         let account = ExpandableOption(identifier: "ExpandableCell", title: "Account")
         let profile = Option(identifier: "SimpleCell", title: "Profile")
         let isPublic = ExpandableOption(identifier: "SwitchCell", title: "Public")
         let caption = Option(identifier: "SimpleCell", title: "Anyone can see this account")
         isPublic.append(caption)
         account.append(profile)
         account.append(isPublic)
         options.append(account)
      
         let group = ExpandableOption(identifier: "ExpandableCell", title: "Group")
         group.append(Option(identifier: "SimpleCell", title: "Group Settings"))
         options.append(group)
         ...
      }
      
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return options.count
      }
      
      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         let option = options[indexPath.row]!
         let cell = tableView.dequeueReusableCellWithIdentifier(option.identifier, forIndexPath: indexPath)
      
         (cell as! CellDescrptionConfigurable).cellDescription = option
         (option as? ExpandCellInformer)?.delegate = self
         return cell
      }
      
      func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
          guard let option = options[indexPath.row] else { return }
          guard let expandableOption = option as? ExpandableOption else { return }
          if expandableOption.identifier == "ExpandableCell" {
              expandableOption.active = !expandableOption.active
          }
      }
      
      func expandableCell(expandableCell: ExpandableCellDescriptor, didChangeActive active: Bool) {
          guard let index = options.indexOf(expandableCell) else { return }
          var indexPaths = [NSIndexPath]()
          for row in 1..<expandableCell.countIfActive {
              indexPaths.append(NSIndexPath(forRow: index + row, inSection: 0))
          }
          if active {
              tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
          } else {
              tableView.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
          }
      }