可使用文本字段扩展的 Tableview 单元格会导致文本字段跳来跳去

Posted

技术标签:

【中文标题】可使用文本字段扩展的 Tableview 单元格会导致文本字段跳来跳去【英文标题】:Tableview cell expandable with text field causes textfield to jump around 【发布时间】:2016-02-06 03:55:27 【问题描述】:

所以我现在一直在尝试创建一个包含可展开部分和一个不可展开部分的表格视图。其中一个可扩展部分应该有 3 个文本字段,您可以在其中编辑文本字段内的测试。在您折叠该部分并再次展开它的那一刻,我能够获得该工作,文本字段突然在上面复制自己,有时会与上面的单元格交换自己。我还没有弄清楚为什么或如何让它不这样做。 这个想法是当用户在字段中输入文本并选择输入时,将文本存储到一个数组中。

代码:

    - (void)viewDidLoad
    [super viewDidLoad];

    if (!expandedSections)
        expandedSections = [[NSMutableIndexSet alloc] init];
    
    manualSensorName = [[NSMutableArray alloc]initWithObjects: @"Sensor",@"",@"2",@"T", nil];


- (void)didReceiveMemoryWarning
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark - Expanding

- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
    if (section>0) return YES;

    return NO;



#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    return 3;


- (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 *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrowUP.png"]];
                cell.accessoryView = arrow;
            
            else
            
                UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrowDOWN.png"]];
                cell.accessoryView = arrow;
            
        
        else 
            if (indexPath.row == 1)
                NSString *flightNumText = [manualSensorName objectAtIndex:indexPath.row];
                cell.textLabel.text = flightNumText;
            
            else if (indexPath.row == 2)
                txtManualSensor = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
                txtManualSensor.placeholder = @"Select";
                txtManualSensor.delegate = self;
                txtManualSensor.autocorrectionType = UITextAutocorrectionTypeNo;
                txtManualSensor.backgroundColor = [UIColor whiteColor];
                [txtManualSensor setBorderStyle:UITextBorderStyleBezel];
                [txtManualSensor setTextAlignment:NSTextAlignmentCenter];
                [txtManualSensor setReturnKeyType:UIReturnKeyDone];
//                UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
//                playerTextField.adjustsFontSizeToFitWidth = YES;
//                playerTextField.textColor = [UIColor blackColor];
//                playerTextField.placeholder = @"SAMPLE";
//                playerTextField.tag = 200;
//                playerTextField.delegate = self;
//                [cell.contentView addSubview:playerTextField];
                cell.textLabel.text = @"Sensor Name";
                [cell addSubview:txtManualSensor];
            
            else if (indexPath.row == 3)
                cell.textLabel.text = @"Some Detail";
                cell.accessoryView = nil;
                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            

        
    
    else 
        cell.accessoryView = nil;
        cell.textLabel.text = @"Normal Cell";

    

    return cell;

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField 
    [manualSensorName replaceObjectAtIndex:2 withObject:textField.text];
    return YES;

-(BOOL) textFieldShouldReturn:(UITextField *)textField

    [textField resignFirstResponder];
    return YES;


// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

    // Return NO if you do not want the specified item to be editable.
    return YES;



#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    if ([self tableView:tableView canCollapseSection:indexPath.section])
        if (!indexPath.row)
            [tableView beginUpdates];

            // 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<rows; i++) 
                NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
                [tmpArray addObject:tmpIndexPath];
            

            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            if (currentlyExpanded) 
                UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrowDOWN.png"]];
                [tableView deleteRowsAtIndexPaths:tmpArray
                                 withRowAnimation:UITableViewRowAnimationFade];
                cell.accessoryView = arrow;
            
            else 
                UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrowUP.png"]];
                [tableView insertRowsAtIndexPaths:tmpArray
                                 withRowAnimation:UITableViewRowAnimationFade];
                cell.accessoryView =  arrow;
            
            NSLog(@"tableview row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
            [tableView endUpdates];
        
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        NSLog(@"selected row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
        if (indexPath.row == 1) 
            // update text fields in cell table view
        
    

【问题讨论】:

您的问题可能在这里得到解答,并附有演示:***.com/a/34997679/218152 该答案是用 Swift 编写的,我在 tableView 上没有 reloadRowsAtIndexPaths,因为我之前曾尝试插入该代码 sn-p。 【参考方案1】:

这可能就像将UITableViewRowAnimationTop 替换为UITableViewRowAnimationFade 一样简单: 当更改didSelectRowAtIndexPath 中的索引时,UITableViewCells 会更改物理位置(请记住,UITableViewUIScrollView),并且滚动条无法跟踪您的intent 是什么。

UITableViewRowAnimationTop 尝试调整滚动位置,但失败。


其他设计注意事项:

不要将模型(要显示的数据数组)与视图模型(显示模型的 UI)混合。在didSelectRowAtIndexPath 中,您应该首先重新排序您的模型,然后将其应用于单元格

考虑不要即时更改索引:您可能更喜欢实际反映视图结构的模型,即树。

您是否注意到您不尊重- (void)tableView:(UITableView *)tableView 并且有时以相同的方法使用self tableView:tableViewself.customTableView?您应该使用传递给您的tableView

【讨论】:

我按照您的建议进行了更改,但行为仍在发生 但是我不明白你在第一个项目符号建议中的意思,所以我没有尝试那个 所以我最终做的是将所有 cellForAtIndexPath 移到自定义单元子类中,这有助于缓解问题。

以上是关于可使用文本字段扩展的 Tableview 单元格会导致文本字段跳来跳去的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tableview 中创建一个具有多个字段的单元格?

将文本字段数据保存在 xcode 中的可扩展表格单元格中

从自定义 tableView 单元格文本字段中获取数据

swift中tableView的单元格高度扩展时更改标签文本

如何在ios中的tableview单元格上的文本字段上返回文本字段上的键盘

tableview单元格内的ios文本字段