繁体   English   中英

如何在 UIScrollView 中使用 UITableView 并接收单元格单击?

[英]How to use UITableView inside UIScrollView and receive a cell click?

我有DiscountListTableViewController ,它在我的应用程序中显示为一个单独的屏幕。 但是还有另一个屏幕( PlaceDetailsViewController ),我需要在底部显示相关的折扣。

目前, PlaceDetailsViewController.viewUIScrollView作为容器,我正在将DiscountListTableViewController.tableView添加到PlaceDetailsViewController viewDidLoad中的这个UIScrollView.content容器。 这有效并且表格视图显示正确,但是无法接收单元格点击。

我知道UITableView继承自UIScrollView并且以某种方式不建议(但不限制)。 然而,从松耦合的角度来看,每个组件都应该以一种可以在其他地方独立使用的方式设计,在我的例子中它是DiscountListTableViewController

PlaceDetailsViewController组件只需PlaceDetailsViewController DiscountListTableViewController ,所以没有逻辑上的理由不能直接使用它。 有什么建议?

回答:不要这样做。

UITableview继承自 ----> UIScrollView : UIView : UIResponder : NSObject

苹果 说:

重要提示:您不应在 UIScrollView 对象中嵌入 UIWebView 或 UITableView 对象。 如果这样做,可能会导致意外行为,因为两个对象的触摸事件可能会混淆并错误处理。

不建议? 读完后感觉有点像“不要做”。不可预测性对于应用程序来说从来都不是一个好行为

重要提示:您不应在 UIScrollView 对象中嵌入 UIWebView 或 UITableView 对象。 如果这样做,可能会导致意外行为,因为两个对象的触摸事件可能会混淆并错误处理。

将分享如何解决。 是否继承了 UIScrollView 并在 PlaceDetailsViewController 中用作容器视图:

@interface PlaceDetailsContainerUIScrollView : UIScrollView

@end

@implementation PlaceDetailsContainerUIScrollView

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
  UIView *result = [super hitTest:point withEvent:event];

  if ([result isKindOfClass:[UIView class]] && (result.tag == kDiscountListTableViewCellTag)
  {
    UITableView *tableView = (UITableView *) [[result.superview superview] superview];

    return tableView;

  }

  return result;
}
@end

另外,不要忘记设置 PlaceDetailsContainerUIScrollView.delaysContentTouches = YES 和 PlaceDetailsContainerUIScrollView.canCancelContentTouches = NO。

此外,需要在 DiscountListTableViewController 方法中进行小修复:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  DiscountDetailsViewController *discountDetailsVC = [[DiscountDetailsViewController alloc] init];

  //[self.navigationController pushViewController:discountDetailsVC animated:YES];   
  // self.navigationController is nill because it's not pushed on nav stack, so will grab the current one:
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

  [appDelegate.navigationController pushViewController:discountDetailsVC animated:YES];
}

2020 年的更新,swift 5.X 允许您的tableviewscrollview

  1. 创建 UITableView 的子类:

     import UIKit final class ContentSizedTableView: UITableView { override var contentSize:CGSize { didSet { invalidateIntrinsicContentSize() } } override var intrinsicContentSize:CGSize { layoutIfNeeded() return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) } }
  2. 将 UITableView 添加到您的布局并在所有方面设置约束。 将它的类设置为 ContentSizedTableView。

  3. 您应该会看到一些错误,因为 Storyboard 没有考虑我们的子类的intrinsicContentSize 在运行时,它将使用我们的 ContentSizedTableView 类中的覆盖

也许这已经晚了,但我设法通过以下方式做到了这一点:

  • 在 UITableView 上禁用滚动
  • 在计算我需要的高度后以编程方式设置 UIScrollView 的内容大小

不应该这样做,因为 UITableView 是 UIScrollView 的子类,根据苹果文档。 只需使用自动布局比计算每个项目大小和停止表格滚动更容易。

苹果文档

您不应在 UIScrollView 对象中嵌入 UIWebView 或 UITableView 对象。 如果这样做,可能会导致意外行为,因为两个对象的触摸事件可能会混淆并错误处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM