当单元格处于焦点时,iOS 在 TableViewCell 上放置一个视图

Posted

技术标签:

【中文标题】当单元格处于焦点时,iOS 在 TableViewCell 上放置一个视图【英文标题】:iOS Place a View on a TableViewCell when cell is in focus 【发布时间】:2014-07-19 12:48:18 【问题描述】:

在 VC 中,我有一个带有自定义单元格“ChartListCell”的 tableView。当用户在任何特定单元格上时,我想在单元格顶部打开一个带有 2 个按钮的视图,并让用户单击任何按钮并对该单元格采取适当的操作。实现此功能的最佳方法是什么?我被困在:-

    选择查找单元格/行的事件。 将视图放置在单元格的位置 - 使其保持在单元格的顶部。 使用 2 个 btns 创建视图 - 以编程方式创建它会更好,以便只能在同一个 VC 中提及事件,还是创建一个 xib 会是更好的选择? 选择丢失时再次隐藏视图。

更新:- 所以我点击单元格,出现视图(如下面的 2 个按钮)。如果我滚动表格,视图将停留在单元格上。一旦我在新视图上点击一个选项,或者点击另一个单元格或外面的某个地方,它就会消失。

更新:- 我创建了一个 xib 文件并在didSelectRowAtIndexPath 中尝试显示视图,但它没有出现。

        // Get the SELECTED CELL
    ChartListCell *cell = (ChartListCell*)[tableView cellForRowAtIndexPath:indexPath];

    NSLog(@"ABOUT TO SHOW VOV");

    NSArray *visitorOptView = [[NSBundle mainBundle] loadNibNamed:@"VisitorsOptionsView" owner:self options:Nil];
    VisitorsOptionsView *vov = [visitorOptView objectAtIndex:0];
    vov.frame = cell.frame;
    [self.view addSubview:vov];
    [self.view bringSubviewToFront:vov];

什么都没有出现。我哪里错了?为了给出与单元格相同的位置,我尝试了 vov.frame = cell.frame ,但我认为我在那一步可能是错误的。那个地方应该还有什么???

实现上述内容的最佳方法是什么?你能帮我指导一下吗?非常感谢任何帮助。

下图显示了我希望符合设计的内容:-

【问题讨论】:

你如何确定哪个单元格有焦点?您是在谈论何时调用 didSelectdidDeselect “单元格处于焦点”和“当用户位于任何特定单元格时”是什么意思?您是在说控件是第一响应者吗? Welp,我们两个人对“焦点”的含义做出了不同但同样好的假设,所以我想现在我投票结束这个问题,因为它不清楚。请更新问题并清楚说明您的意思,可能包括 tableview 外观的屏幕截图,以及对您要添加到屏幕的这些临时按钮的更好解释。 @nhgrif,添加了屏幕截图和更多关于焦点术语和我正在寻找的内容的说明。 所以我点击单元格,视图出现。如果我滚动表格,视图将停留在单元格上。一旦我在新视图上点击一个选项,它就会消失。这是对预期行为的充分解释吗? 【参考方案1】:

我为你做了这个演示项目:http://goo.gl/Y6GFmj,你可以下载

您可以将视图添加到表格单元格而不是视图中。您需要子类化您的表格视图单元格并添加一个属性来保存覆盖视图。

    @interface MyTableViewCell : UITableViewCell
    @property (weak, nonatomic) UIView * overlayView;
    @end

请注意,覆盖视图应该是一个弱属性,因为单元格的视图将对其具有强引用,就像 IBOutlet 一样。

您需要在表格视图控制器中添加另一个属性来保存最后选择的索引路径,这样当您选择新行时,您可以删除旧行中的覆盖视图。

    @property (strong, nonatomic) NSIndexPath * lastSelectedRow;

使用以下函数从单元格中删除覆盖视图

    - (void)removeViewInCellOfIndexPath:(NSIndexPath *)indexPath
    
        if (!indexPath)
        return;

        MyTableViewCell * cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
        if (cell.overlayView)
        
            [cell.overlayView removeFromSuperview];
        

    

现在你可以处理选择了:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    
        // deselecte the row
        [tableView deselectRowAtIndexPath:indexPath animated:NO];

        // remove the overlay view from the last selected row
        [self removeViewInCellOfIndexPath:self.lastSelectedRow];

        // add overlay view to this row
        MyTableViewCell * cell = (MyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

        // note the origin of the frame is (0, 0) since you are adding itto the cell instead of the table view
        UIView * view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height)];
        view.backgroundColor = [UIColor greenColor];
        [cell.contentView addSubview:view];

        // remember this view and this indexpath
        cell.overlayView = view;
        self.lastSelectedRow = indexPath;
    

【讨论】:

非常感谢 Sen。您的演示、Geet 的回答和引用其他一些网站,都帮助我解决了我的问题,并且可以通过它。【参考方案2】:

我做过类似的事情,我所做的是在创建自定义单元格时,我在底部放置了另一个包含两个按钮的视图,将这两个按钮作为它们类的 IBOutlets。

当我使用 CellForROwAtIndexpath 中的常用方法将其加载到表视图中时,我定义如下...

- (UITableViewCell *)couchTableSource:(CBLUITableSource*)source
                cellForRowAtIndexPath:(NSIndexPath *)indexPath


      NSString *cellid=@"Cell";

            CustomTableCell* cell=(CustomTableCell*)[_Mytableview     dequeueReusableCellWithIdentifier:cellid];

            if(cell==nil)
                
                NSArray *nib=[[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:self options:nil];
                cell=[nib objectAtIndex:0];
                

    [cell.firstButton addTarget:self action:@selector(firstButtonClicked:event:) forControlEvents:UIControlEventTouchUpInside];
        [cell.secondButton addTarget:self action:@selector(SecondButtonClicked:event:) forControlEvents:UIControlEventTouchUpInside];


我维护了一个全局整数标志作为 SelectedIndex 并按如下方式使用它

在 didSelectRowAtIndexPath 中我做了这样的事情..

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

 if(selectedIndex == indexPath.row)
        
        selectedIndex = -1;
        [_Mytableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

        return;
        

    //First we check if a cell is already expanded.
    //If it is we want to minimize make sure it is reloaded to minimize it back
    if(selectedIndex >= 0)
        
        NSIndexPath *previousPath = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
        selectedIndex = indexPath.row;
        [_Mytableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
        

    //Finally set the selected index to the new selection and reload it to expand
    selectedIndex = indexPath.row;

    [_Mytableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];



也是 heightForRowAtIndexPath 中最重要的一步

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath


    if(indexPath.row == selectedIndex)
        

        return  (return the actual size of the cell, Including the view with two buttons);
        
    else
        
        return (return the size of cell -(the size of view containing the two buttons));
        

在 viewWillAppear 中确保指定这个,以便单元格在出现时正常

-(void)viewWillAppear:(BOOL)animated


  selectedIndex=-1;

   [myTableView reloadData];

【讨论】:

非常感谢吉特。您的回答、Sen 的回答以及引用其他一些网站,都帮助我解决了我的问题,并且可以通过它。

以上是关于当单元格处于焦点时,iOS 在 TableViewCell 上放置一个视图的主要内容,如果未能解决你的问题,请参考以下文章

提供容器的摘要,如带有旁白的 tableview

在 UISearchController 处于活动状态时选择 tableview 中的单元格,不显示下一个视图?

ios:在点击collectionview单元格或tableview单元格时禁用第二个触摸事件

为 iOS 选择 TableView 单元格时视图已更改

向下滚动时不会出现 Swift Expandable tableView 单元格按钮

无法从swift ios中的一段tableview中删除单元格