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. The problem is that when I scroll the 开发者_C百科table to the bottom the added UIView is scrolling with the table. 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:
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:
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:
-(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.
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. 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. 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.
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.
So here is my code. Note the property, the content inset on the table view and the -scrollViewDidScroll:
delegate method implementation. 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. 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
Add your view to the superview of the table view (if possible;
UITableViewController
makes this impossible).Add your view to the table view and reposition it in the
-scrollViewDidScroll:
delegate method (UITableViewDelegate
is a sub-protocol ofUIScrollViewDelegate
).
I had a similar problem where I wanted to add a loading indicator on top of my UITableViewController. To solve this, I added my UIView as a subview of the window. 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. Here's what I did (assuming myCustomView was established somewhere else in the file):
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];
}
精彩评论