如何在当前UITableViewController上添加UIView

时间:2011-01-09 21:18:40

标签: iphone objective-c ios4

我很难在UITableViewController的viewDidLoad方法中添加子视图(UIView)

这有效:

[self.view addSubview:self.progView];

但是你可以通过UIView progView看到表格单元格出血。

我尝试过这种方法:

[self.view.superview insertSubview:self.progView aboveSubview:self.view];

尝试将progView,UIView添加到当前视图上方的superview。当我尝试这个时,UIView永远不会出现。

- 更新 -

以下是最新的尝试:

UIView *myProgView = (UIView *)self.progView; //progView is a method that returns a UIView

[self.tableView insertSubview:myProgView aboveSubview:self.tableView]; 
[self.tableView bringSubviewToFront:myProgView];

结果与[self.view addSubview:self.progView]相同; UIView出现但似乎在桌子后面。

21 个答案:

答案 0 :(得分:93)

我尝试了上面的方法,但没有让它发挥作用。我还发现它需要太多的配置和代码,因为它需要从头开始设置表视图(这可以从故事板中轻松完成)。

相反,我添加了一个视图,我想将我的UITableView添加到UITableViewController的UINavigationController视图中,如下所示:

[self.navigationController.view addSubview:<view to add above the table view>];

这种方法要求您已将UITableViewController嵌入到UINavigationController中,但即使您不需要导航控制器,仍然可以使用此方法并隐藏导航栏。

答案 1 :(得分:28)

这实际上非常简单易行 - 只需要一些重新布线。我遇到了类似的情况,并将其编码为允许我在表格视图的顶部添加加载屏幕。此方法还允许您将静态表格单元格与您自己的内容一起使用。

如果您的控制器是Storyboard或XIB中的UITableViewController,并且您希望在保留现有表视图的同时将self.view重新分配给标准UIView:

将这些实例变量添加到标题文件

IBOutlet UITableView *tableViewReference; // to keep a reference to the tableview
UIView *viewReference; // a reference to the new background view

Storyboard或XIB文件中:将tableView中的UITableViewControllertableViewReference变量相关联。

然后在实施文件

// Override the default accessors of the tableview and view
- (UITableView*)tableView { return tableViewReference; }
- (UIView*)view { return viewReference; }

- (void)viewDidLoad
{
    [super viewDidLoad];

    // instantiate the new self.view, similar to the tableview
    viewReference = [[UIView alloc] initWithFrame:tableViewReference.frame];
    [viewReference setBackgroundColor:tableViewReference.backgroundColor];
    viewReference.autoresizingMask = tableViewReference.autoresizingMask;
    // add it as a subview
    [viewReference addSubview:tableViewReference];

    /* remainder of viewDidLoad */

}

虽然看起来很奇怪,但UITableViewController在幕后引用很多古怪的东西。您需要等到viewDidLoad才能进行交换。在此之后,访问者将指向正确的UIViewUITableView

使用方法: 像

这样的东西
    [self.view addSubview:myView];

会在表格视图前添加UIView myView,而不会myView滚动表格视图的内容。

注意:在指出该解决方案包含临界矛盾代码后,对此答案进行了编辑。 UITableViewController对它所拥有的引用做了一些奇怪的事情。一些更仔细的测试得出了这个更简单的答案:)

答案 2 :(得分:11)

您可以增加视图图层的zPosition。

这将使其显示在其他视图上方(默认情况下zPosition等于0)

self.progView.layer.zPosition++;
[self.view addSubview:self.progView];

答案 3 :(得分:11)

我已经能够使用uiviewcontroller包含在uitableviewcontroller上添加子视图。

UITableViewController在静态单元格方面实际上非常方便,这可能是唯一一个“只使用uitableview”的常见答案实际上不可行的时候。

所以我就是这样做的。

  1. 为您的 UITableViewController 提供一个StoryBoard标识符,即 MyStaticTableView
  2. 创建一个全新的 UIViewController 子类并将其命名为 UITableViewControllerContainer
  3. 将此控制器放在故事板中 UITableViewController 的位置
  4. 将子视图添加到新控制器并将其链接到名为“ view_container ”的商店
  5. on you UITableViewControllerContainer viewDidLoad method
  6. 添加如下代码:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        UITableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MyStaticTableView"];
        [self addChildViewController:vc];
        [self.view_container addSubview:vc.view];
    }
    

    您可能遇到的问题:

    1. 如果你有额外的顶级空间,那么一定要将标志“想要全屏”添加到你的UITableViewController
    2. 如果它未在UITableViewControllerContainer上正确调整大小
    3. 添加代码:

      - (void)viewWillAppear:(BOOL)animated
      {
          [[self.view_container.subviews lastObject] setFrame:self.view.frame];
      }
      

      此时,您可以从UITableViewController直接使用

      访问容器视图
        

      self.view.superview.superview

      并且您添加到它的任何内容都将显示在您的表视图控制器

答案 4 :(得分:7)

Swift 2018

以下是故事板的方式:

1)在故事板中添加视图 enter image description here

2)将它与UITableViewController类链接:

@IBOutlet weak var copyrightLabel: UILabel!

3)将其添加到代码中

self.navigationController?.view.addSubview(copyrightView)
copyrightView.frame = CGRect(x: 0,
                            y: self.view.bounds.size.height - copyrightView.bounds.size.height,
                            width: self.view.bounds.size.width,
                            height: copyrightView.bounds.size.height)

4)Voilla!
enter image description here

视图不会随表格视图滚动。它可以从故事板中轻松设计。

答案 5 :(得分:6)

问题是view的{​​{1}}属性与UITableViewController属性相同。这意味着根视图总是一个表视图控制器,任何作为子视图添加的内容都将受到表视图功能的限制。这有其他不良副作用,例如您可能不希望它们滚动的子视图。

这里有几个选项。您可以覆盖tableView并安装自己的视图和表格视图:

loadView

然后,当您需要添加子视图时,请根据需要在// note: untested - (void)loadView { self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease]; self.view.backgroundColor = [UIColor whiteColor]; UITableView *tblView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain ]; tblView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ; self.tableView = tblView; [self.view addSubview:tblView]; [tblView release]; } 下方或上方添加。

另一个选择就是创建一个self.tableView子类来完成你需要的工作。 UIViewController老实说,并没有增加那么多,它实现的小功能很容易复制。像Recreating UITableViewController to increase code reuse这样的文章很容易解释如何做到这一点。

答案 6 :(得分:6)

我遇到了类似的问题,并使用以下代码解决了问题:

     [self.navigationController.view insertSubview:<subview> 
       belowSubview:self.navigationController.navigationBar];

使用Stack中的控制器将视图插入到正确的位置。

答案 7 :(得分:6)

由于UITableViewController是UIViewController的子类,因此您需要将所需的视图添加到其superview中。

Swift:
self.view.superview?.addSubview(viewTobeAdded)

Objective C:
[self.view.superview addSubview: viewTobeAdded];

答案 8 :(得分:5)

Apple示例“iPhoneCoreDataRecipes”正在使用NIB将标头加载到UITableView上。 见here

答案 9 :(得分:4)

我在桌子上方添加了一张图片。我用了这段代码:

self.tableView.tableHeaderView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header.png"]];

答案 10 :(得分:2)

swift解决方案(相当于Daniel Saidi):

如果您的控制器是Storyboard或XIB中的UITableViewController,并且您希望在保留现有表视图的同时将self.view重新分配给标准UIView:

@IBOutlet var tableViewReference: UITableView!
var viewReference: UIView!

然后在您的实施文件中:

将这些实例变量添加到表视图控制器文件中:

override var tableView: UITableView! {
    get { return tableViewReference }
    set { super.tableView = newValue }
}

override var view: UIView! {
    get { return viewReference }
    set { super.view = newValue }
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.edgesForExtendedLayout = UIRectEdge.None
    self.extendedLayoutIncludesOpaqueBars = false
    self.automaticallyAdjustsScrollViewInsets = false

    //rewiring views due to add tableView as subview to superview
    viewReference = UIView.init(frame: tableViewReference.frame)
    viewReference.backgroundColor = tableViewReference.backgroundColor
    viewReference.autoresizingMask = tableViewReference.autoresizingMask
    viewReference.addSubview(tableViewReference)
}

在Storyboard或XIB文件中:将UITableViewController中的tableView连接到tableViewReference变量。

然后您可以按如下方式添加子视图:

self.view.addSubView(someView)

答案 11 :(得分:2)

iOS 11更新:

现在可以在对安全区域使用AutoLayout约束时将子视图添加到UITableView。这些视图不会沿着TableView滚动。

此示例将导航栏下方的视图放置在UITableView

UITableViewController之上
[self.tableView addSubview:self.topBarView];
[NSLayoutConstraint activateConstraints:@[
    [self.topBarView.topAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.topAnchor],
    [self.topBarView.leadingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.leadingAnchor],
    [self.topBarView.trailingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.trailingAnchor],
    [self.topBarView.heightAnchor constraintEqualToConstant:40.0]
]];

答案 12 :(得分:1)

尝试:[self.view bringSubviewToFront:self.progView];

或者您可以尝试将self.progView添加到表格视图中。

答案 13 :(得分:1)

要在当前UITableViewController上方添加customView,它必须是使用Daniel所评论的“ self.navigationController.view addSubview:customView”的好方法。

但是,如果实现实现用作navigationBar的customView,Daniel的方法可能会导致默认结果意外发生,或者导致UITableViewController前后的其他navigationViewController上的custom navigationBar出现意外情况。

最好的简单方法是将UITableViewController转换为UIViewController,对子视图的布局没有限制。但是,如果您要处理大量的,冗长的旧版UITableViewController代码,则情况完全不同。我们没有任何转换时间。

在这种情况下,您可以简单地劫持UITableViewController的tableView并解决整个问题。

我们应该知道的最重要的事情是UITableViewController的'self.view.superview'是nil,'self.view'是UITableView本身。

首先,劫持UITableVIew。

UITableView *tableView = self.tableView;

然后,用新的UIView替换'self.view'(现在为UITableView),以便我们可以无限制地布局customViews。

UIView *newView = UIView.new;
newView.frame = tableView.frame;
self.view = newView;

然后,将之前被劫持的UITableView放到新的self.view上。

[newView addSubview:tableView];
tableView.translatesAutoresizingMaskIntoConstraints = NO;
[tableView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
[tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
[tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
[tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;

现在,我们可以在UITableViewController上这个崭新的'self.view'上做任何想要的事情。

自定义视图,然后将其添加为子视图。

UIView *myNaviBar = UIView.new;
[myNaviBar setBackgroundColor:UIColor.cyanColor];
[self.view addSubview:myNaviBar];

myNaviBar.translatesAutoresizingMaskIntoConstraints = NO;
[myNaviBar.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
[myNaviBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
[myNaviBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
[myNaviBar.heightAnchor constraintEqualToConstant:90].active = YES;

gif

答案 14 :(得分:1)

快捷键4

这是我们在重新构建视图层次结构时所用答案的最简化版本。这种方法不需要为情节提要/笔尖提供额外的插座,并且还可以与以编程方式构造的实例一起使用。

class MyTableViewController: UITableViewController {

    var strongTableView: UITableView?

    override var tableView: UITableView! {
        get {
            return strongTableView ?? super.tableView
        }
        set {
            strongTableView = newValue
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // theoretically we could use self.tableView = self.tableView but compiler will not let us assign a property to itself
        self.tableView = self.view as? UITableView
        self.view = UIView(frame: self.tableView!.frame)
        self.view.addSubview(tableView)

    }

}

答案 15 :(得分:1)

您可以简单地将以下代码放在viewDidAppear中:

[self.tableView.superview addSubview:<your header view>];

答案 16 :(得分:1)

使用一个(或多个)委托方法(UITableViewDelegate)将UIView保留在UITableViewController中的表视图之上。

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.addSubview(headerView)
}

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    tableView.addSubview(overlayView) // adds view always on top
}
// if using footers in table view
tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) { ... }

由于视图只能有一个超级视图,接缝也是很好的解决方案,如果我错了,请纠正我。仍然得到60fps,这对我来说很好。

答案 17 :(得分:0)

这对我有用:

self.view.superview?.addSubview(yourCustomView)
self.view.bringSubviewToFront(yourCustomView)

答案 18 :(得分:0)

尝试这样的事情:

[self.tableView addSubview:overlayView];
overlayView.layer.zPosition = self.tableView.backgroundView.layer.zPosition + 1;

答案 19 :(得分:0)

可能有理由不这样做,但到目前为止这对我有用。如果你使用ap

viewDidLayoutSubviews内你可以运行它,但请确保只运行一次

self.searchTableView = [[UITableView alloc] initWithFrame:self.tableView.frame style:UITableViewStylePlain];
self.searchTableView.backgroundColor = [UIColor purpleColor];
[self.view.superview addSubview:self.searchTableView];

答案 20 :(得分:0)

我有一个类似的问题,我想在我的UITableViewController上添加一个加载指示器。为了解决这个问题,我将我的UIView添加为窗口的子视图。这解决了这个问题。这就是我做到的。

-(void)viewDidLoad{
    [super viewDidLoad];
    //get the app delegate
    XYAppDelegate *delegate = [[UIApplication sharedApplication] delegate];

    //define the position of the rect based on the screen bounds
    CGRect loadingViewRect = CGRectMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2, 50, 50);
    //create the custom view. The custom view is a property of the VIewController
    self.loadingView = [[XYLoadingView alloc] initWithFrame:loadingViewRect];
    //use the delegate's window object to add the custom view on top of the view controller
    [delegate.window addSubview: loadingView]; 
}