简体   繁体   English

iOS:将 UIView 放在固定位置的 UITableView 之上

[英]iOS: Place UIView on top of UITableView in fixed position

I need to put a UIView (for ads) on top of a UITableView in my iphone app.我需要在我的 iphone 应用程序中的 UITableView 顶部放置一个 UIView(用于广告)。 The problem is that when I scroll the table to the bottom the added UIView is scrolling with the table.问题是,当我将表格滚动到底部时,添加的 UIView 与表格一起滚动。 What I want is for it to be fixed on the bottom of the screen.我想要的是将它固定在屏幕底部。 Is there a way to do that?有没有办法做到这一点?

This is the code which I have used to add the UIView to the table:这是我用来将 UIView 添加到表的代码:

 awView = [AdWhirlView requestAdWhirlViewWithDelegate:self]; 
 awView.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
 [self.tableView addSubview:awView];

Here is how it worked for me.这是它对我的工作方式。 The Ad stays at the bottom of the view.广告停留在视图的底部。

In ViewDidLoad, in YourController.m:在 ViewDidLoad 中,在 YourController.m 中:

awView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
awView.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height-kAdWhirlViewHeight/2);
[self.view addSubview:awView];

Then add this method somewhere in the same .m file:然后在同一个 .m 文件中的某处添加这个方法:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGRect newFrame = awView.frame;
    newFrame.origin.x = 0;
    newFrame.origin.y = self.tableView.contentOffset.y+(self.tableView.frame.size.height-kAdWhirlViewHeight);
    awView.frame = newFrame;
}

Don't forget to declare awView.不要忘记声明 awView。

I appreciate this is an old question.我很欣赏这是一个老问题。 But I've found the answers either with false information in part and unclear snippets.但我已经找到了部分错误信息和不清楚片段的答案。 So for what it's still worth, here is how I added a "floating" view to the bottom of my UITableViewController 's view.所以对于它仍然值得,这里是我如何在UITableViewController的视图底部添加一个“浮动”视图。 Yes, you can do that, even if the accepted answers says you cannot.是的,您可以这样做,即使公认的答案说您不能。

In your -viewDidLoad method, you can create a view which we will name bottomFloatingView.在您的-viewDidLoad方法中,您可以创建一个视图,我们将其命名为 bottomFloatingView。 This is also set up as a property.这也设置为属性。

Be sure to add a content inset to the bottom of your table view, this will avoid hiding any of the table's content with your floating view.确保在表格视图的底部添加内容插入,这将避免使用浮动视图隐藏表格的任何内容。

Next, you should use the UIScrollViewDelegate to update the frame of the floating view.接下来,您应该使用UIScrollViewDelegate来更新浮动视图的框架。

The illusion will be that your view is stuck to the bottom.错觉是你的观点被卡在了底部。 In reality, this view is moving all the time you are scrolling, and is always being computed to appear at the bottom.实际上,此视图在您滚动时一直在移动,并且始终被计算为显示在底部。 Scroll views are very powerful !滚动视图非常强大! And probably are one of the most underrated UIKit classes I think.并且可能是我认为最被低估的 UIKit 类之一。

So here is my code.所以这是我的代码。 Note the property, the content inset on the table view and the -scrollViewDidScroll: delegate method implementation.注意属性,表格视图上的内容插入和-scrollViewDidScroll:委托方法实现。 I created my floating view in my storyboard which is why you can't see that being setup.我在我的故事板中创建了我的浮动视图,这就是为什么你看不到它正在设置的原因。

Also don't forget you should probably also use KVO to observe changes to the table view's frame.另外不要忘记你可能还应该使用 KVO 来观察 table view 框架的变化。 It's possible for that to change over time, the easiest way to test that is by toggling on and off the in call status bar in the simulator.它可能会随着时间的推移而改变,最简单的测试方法是打开和关闭模拟器中的通话状态栏。

Last thing, if you're using section header views in your table view, those views will be the top most view in the table view so you'll also want to bring your floating view to the front, do this when you change its frame.最后一件事,如果您在表格视图中使用部分标题视图,这些视图将是表格视图中最顶部的视图,因此您还希望将浮动视图置于最前面,在更改其框架时执行此操作.

@interface MyTableViewController ()
@property (strong, nonatomic) IBOutlet UIView *bottomFloatingView;
@end

@implementation MyTableViewController

static NSString *const cellIdentifier = @"MyTableViewCell";

- (void)dealloc
{
    [self.tableView removeObserver:self forKeyPath:@"frame"];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.tableView addSubview:self.bottomFloatingView];

    self.tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, CGRectGetHeight(self.bottomFloatingView.bounds), 0.0);
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, CGRectGetHeight(self.bottomFloatingView.bounds), 0.0);

    [self.tableView addObserver:self
                     forKeyPath:@"frame"
                        options:0
                        context:NULL];
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];

    return cell;
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [self adjustFloatingViewFrame];
}

#pragma mark - KVO

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if([keyPath isEqualToString:@"frame"]) {
        [self adjustFloatingViewFrame];
    }
}

- (void)adjustFloatingViewFrame
{
    CGRect newFrame = self.bottomFloatingView.frame;

    newFrame.origin.x = 0;
    newFrame.origin.y = self.tableView.contentOffset.y + CGRectGetHeight(self.tableView.bounds) - CGRectGetHeight(self.bottomFloatingView.bounds);

    self.bottomFloatingView.frame = newFrame;
    [self.tableView bringSubviewToFront:self.bottomFloatingView];
}

@end
  1. Add your view to the superview of the table view (if possible; UITableViewController makes this impossible).将您的视图添加到表视图的超级视图(如果可能; UITableViewController使这成为不可能)。

  2. Add your view to the table view and reposition it in the -scrollViewDidScroll: delegate method ( UITableViewDelegate is a sub-protocol of UIScrollViewDelegate ).将您的视图添加到表视图并在-scrollViewDidScroll:委托方法( UITableViewDelegateUIScrollViewDelegate的子协议)中重新定位它。

I had a similar problem where I wanted to add a loading indicator on top of my UITableViewController.我有一个类似的问题,我想在 UITableViewController 之上添加一个加载指示器。 To solve this, I added my UIView as a subview of the window.为了解决这个问题,我添加了我的 UIView 作为窗口的子视图。 That solved the problem.那解决了问题。 This is how I did it.我就是这样做的。

-(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]; 
}

For people like me looking for a simple solution using Swift, these answers are kind of outdated.对于像我这样正在寻找使用 Swift 的简单解决方案的人来说,这些答案有点过时了。 Here's what I did (assuming myCustomView was established somewhere else in the file):这是我所做的(假设 myCustomView 是在文件中的其他地方建立的):

func scrollViewDidScroll(_ scrollView: UIScrollView) {
   
    let pixelsFromBottom = CGFloat(20)//or whatever the
    let theHeight = self.tableView.frame.height + scrollView.contentOffset.y
    myCustomView.frame = CGRect(x: 0, y: theHeight - pixelsFromBottom , width: self.view.frame.width, height: myCustomView.frame.height)

}
- (void)viewDidLoad
{
    [super viewDidLoad];

    footerView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-64, SCREEN_WIDTH, 64)];
    footerView.backgroundColor = [UIColor blueColor ];
    [self.navigationController.view addSubview:footerView];
}   

- (void)dealloc
{
    [footerView removeFromSuperview];
}

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

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