将按钮数组添加到适当的表格行

Posted

技术标签:

【中文标题】将按钮数组添加到适当的表格行【英文标题】:Adding Array of Buttons to Appropriate Table Rows 【发布时间】:2014-11-29 00:47:45 【问题描述】:

我正在尝试动态填充带有按钮行的表格。启动表时,我将其传递给包含正确按钮的数组。按钮的数量以及行的数量会有所不同。这有效,直到我需要创建一个新行(即第一行的按钮太多)。假设我将其限制为每行 4 个按钮。然后我的按钮从第 2 行开始,而不是应该的第 1 行。它们也会被剪裁在正确的边界上。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSInteger rows = 0;  // No rows if section is unknown!
    switch (section)
    
        case TableViewSectionFormatButtons:
        
            if ([[self fileTypeButtonsArray] count] % kButtonsPerRow)
                return ([[self fileTypeButtonsArray] count] / kButtonsPerRow) + 1;
            else
                return [[self fileTypeButtonsArray] count] / kButtonsPerRow;
        
            break;
        case TableViewSectionExportSwitches:
            rows = 4;
            break;
        case TableViewSectionExportButton:
            rows = 1;
            break;
        default:
            break;
    

    return rows;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *defaultCellIdentifier = @"defaultCellIdentifier";
    static NSString *detailCellIdentifier = @"detailCellIdentifier";

    UITableViewCell *cellToReturn = nil;

    // Usage note: Both kinds of cells get created every time, which is arguably wasteful.  Since there aren't many rows involved
    // it's simpler just to ignore the one that we don't need.  Assign the one we want to cellToReturn.

    UITableViewCell *defaultCell = [tableView dequeueReusableCellWithIdentifier:defaultCellIdentifier]; // Image on left
    if (defaultCell == nil) 
        defaultCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:defaultCellIdentifier];
    

    UITableViewCell *detailCell = [tableView dequeueReusableCellWithIdentifier:detailCellIdentifier]; // Text on right
    if (detailCell == nil) 
        detailCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:detailCellIdentifier];
    

    // Clear old values
    defaultCell.textLabel.textAlignment = NSTextAlignmentLeft;
    defaultCell.accessoryType = UITableViewCellAccessoryNone;
    defaultCell.accessoryView = nil;
    defaultCell.imageView.image = nil;

    detailCell.accessoryType = UITableViewCellAccessoryNone;
    detailCell.imageView.image = nil;


    switch (indexPath.section) 
        case TableViewSectionFormatButtons: 

            for (int i = 0; i < [self.fileTypeButtonsArray count]; i++)
            
                UIButton *currentButton = (UIButton *)[self.fileTypeButtonsArray objectAtIndex:i];
                [currentButton setTag:i];

                [currentButton setFrame:CGRectMake((kButtonPadding + (i * (kButtonWidth + kButtonPadding))), kButtonPadding, kButtonWidth, kButtonHeight)];
                [defaultCell.contentView addSubview:currentButton];
            

            defaultCell.selectionStyle = UITableViewCellSelectionStyleNone;



            cellToReturn = defaultCell;
        
            break;

        case TableViewSectionExportSwitches: 

            defaultCell.selectionStyle = UITableViewCellSelectionStyleNone;

            if (indexPath.row == 0) 
                defaultCell.textLabel.text = NSLocalizedString(@"synopsisSwitchLabel", @"Synopsis - Export switch label to indicate if Synopsis text should be included in export.");
                self.synopsisSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
                defaultCell.accessoryView = self.synopsisSwitch;
//                self.synopsisSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsShowNotesIndicatorKey];

                [self.synopsisSwitch addTarget:self action:@selector(synopsisSwitchValueChanged:) forControlEvents: UIControlEventValueChanged];

            

            else if (indexPath.row == 1)
            
                defaultCell.textLabel.text = NSLocalizedString(@"bodySwitchLabel", @"Body - Export switch label to indicate if Body text should be included in export.");
                self.bodySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
                defaultCell.accessoryView = self.bodySwitch;

//                self.bodySwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsShowNotesIndicatorKey];
                [self.bodySwitch addTarget:self action:@selector(bodySwitchValueChanged:) forControlEvents: UIControlEventValueChanged];
            

            else if (indexPath.row == 2)
            
                defaultCell.textLabel.text = NSLocalizedString(@"notesSwitchLabel", @"Notes - Export switch label to indicate if Notes should be included in export.");

            self.notesSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
                defaultCell.accessoryView = self.notesSwitch;

//                self.notesSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsShowExpandedOutlineKey];
                [self.notesSwitch addTarget:self action:@selector(notesSwitchValueChanged:) forControlEvents: UIControlEventValueChanged];
            

            else if (indexPath.row == 3)
            
                defaultCell.textLabel.text = NSLocalizedString(@"imagesSwitchLabel", @"Images - Export switch label to indicate if Images should be included in export.");
                self.imagesSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
                defaultCell.accessoryView = self.imagesSwitch;

//                self.imagesSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsStoryboardModeKey];
                [self.imagesSwitch addTarget:self action:@selector(imagesSwitchValueChanged:) forControlEvents: UIControlEventValueChanged];
            

            cellToReturn = defaultCell;
        
            break;

        case TableViewSectionExportButton:
        
            defaultCell.textLabel.textAlignment = NSTextAlignmentCenter;
            if (indexPath.row == 0)
            
                defaultCell.textLabel.text = NSLocalizedString(@"nextButtonTitle", @"Next - Button title indicating user is ready to proceed with Export.");
                defaultCell.textLabel.textColor = [UIColor blueColor];
            

            cellToReturn = defaultCell;
        
            break;

    

    return cellToReturn;

示例按钮超过 1 行 - 错误

示例按钮适合 1 行 - 好

我意识到我只是在告诉它继续在彼此的右侧添加按钮。我很难过如何告诉它将它们放入哪些行。也很难过为什么它们从第二行(索引 1)而不是第一行(索引 0)开始。感谢您的帮助。

【问题讨论】:

可以编辑您的问题以包含您的整个 cellForRowAtIndexPath 方法吗? 当然。它很大,里面有一些不相关的东西,但如果有帮助的话...... 【参考方案1】:

numberOfRowsInSection: 方法中,如果按钮整齐地放入行中,您的TableViewSectionFormatButtons: 会添加一行,即if ([[self fileTypeButtonsArray] count] % kButtonsPerRow);但这听起来与您想要做的完全相反。如果您的按钮不能整齐地放在其上方的行中,这听起来好像您只想添加额外的一行,在这种情况下,我建议您使用一行来代替:

case TableViewSectionFormatButtons: 
    return ([[self fileTypeButtonsArray] count] + kButtonsPerRow - 1) / kButtonsPerRow;

简单地对整数除法进行四舍五入。

至于您的 cellForRowAtIndexPath: 方法,(1)您需要考虑每行按钮的数量,即在您的算法中有 kButtonsPerRow,(2)您需要知道要添加到哪一行, (3) 使用该信息,您只想将属于当前行的按钮放在当前行中,因此您不希望该循环从 0 开始并一直到按钮数组的末尾。例如:

case TableViewSectionFormatButtons: 

    // Calculate the index of the first button in the current row
    int firstButtonIndex = indexPath.row * kButtonsPerRow;

    // Then starting from that index place kButtonsPerRow within that row
    for (int i = firstButtonIndex ; i < firstButtonIndex + kButtonsPerRow ; i++) 

        if (self.fileTypeButtonsArray.count > i) 
            UIButton *currentButton = (UIButton *)[self.fileTypeButtonsArray objectAtIndex:i];
            [currentButton setTag:i];
            [currentButton setFrame:CGRectMake((kButtonPadding + ((i-firstButtonIndex) * (kButtonWidth + kButtonPadding))), kButtonPadding, kButtonWidth, kButtonHeight)];
            [defaultCell.contentView addSubview:currentButton];
        
    

    defaultCell.selectionStyle = UITableViewCellSelectionStyleNone;
    cellToReturn = defaultCell;

类似的东西应该可以工作。

附:您在每个cellForRowAtIndexPath: 期间都重复使用单元格并添加按钮作为子视图这一事实可能会导致一些问题。如果您要以您已经在代码中完成的方式清除旧值,也许您还应该删除同一位置的旧按钮,例如:

// Clear old values
defaultCell.textLabel.textAlignment = NSTextAlignmentLeft;
defaultCell.accessoryType = UITableViewCellAccessoryNone;
defaultCell.accessoryView = nil;
defaultCell.imageView.image = nil;

for (UIView *view in [defaultCell subviews]) 
    if ([view isKindOfClass:[UIButton class]]) 
        [view removeFromSuperview];
    

【讨论】:

感谢您周到而详细的回复。关于 numberOfRowsInSection,您是绝对正确的。它给了我想要的结果,但不是出于正确的原因。 cellForRowAtIndexPath 在传递按钮数大于每行允许的按钮数的数组时崩溃。由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArrayM objectAtIndex:]:索引 5 超出范围 [0 .. 4]。我相信问题出在这一行:for (int i = firstButtonIndex ; i @DenVog 是的,你是对的。我将更新我的答案以包含该案例。 明白了。非常感谢你。感谢您的帮助。 你是对的。单元的重用是丑陋的代码,有时会产生意想不到的后果。我还没有找到更好的混合单元类型的方法(即 Apple 设置屏幕)。它与我最初的问题没有直接关系,所以我将把它带到一个单独的线程中。

以上是关于将按钮数组添加到适当的表格行的主要内容,如果未能解决你的问题,请参考以下文章

如何将行动态添加到表格布局中

如何将已输入的表单数据添加到表格行?

以 ASP.NET MVC 表格形式动态添加行

PyQt的TableWidget如何做一个添加行的按钮?

如何将点击处理程序添加到单元格表格构建器的子行

表格标题中的按钮以加载不同的表格视图