I'm trying to insert a view behind the cells of a uitableview but I can't find a way to do it properly. Everytime I add a subview to self.view or self.tableview, it goes on the foreground, even if I use the method "sendSubviewToBack:" ...
Do someone have an idea on how to achieve it ?
PS : I don't want to use self.tableview.backgroundView because the view is fixed.
Thanks
I solved it by calling [self.view sendSubviewToBack:self.myBackgroundView] in tableView:willDisplayCell:forRowAtIndexPath:. This will put the view behind each cell.
What you experience is logical. The self.view of a UITableView is indeed the table view. If you insert a subview, it is inserted on top of the table view - and there is no way to send it to the back.
Solution 1
The most flexible solution is to switch to a UIViewConntroller and implement the table view behaviour yourself. You need to
insert your own table view as a #property. This is now a subview of self.view. You can do this in code or in IB.
declare and implement the <UITableViewDelegate> and <UITableViewDatasource> protocols
set the delegate and datasource properties of the table view to self
insert any other subviews at will and shuffle them around as you wish.
Solution 2
If you just want to display something behind the tableView you might be able to use the table view property backgroundView. This will display behind the cells, but you will have limited control over the view's size (which you could again solve with further subviews of the background view). Also, you need to make sure your cells are transparent.
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
with index 0 will take the View to position which is the back-most one.
This is a method on UIView.
Since UITableView Inherits from UIScrollView : UIView : UIResponder : NSObject. I guess this would help.
Related
I have a UIView with a lot of components enclosed in it and would like to update some of them if the view is removed or if its parent view controller is popped/pushed. Is it possible for a UIView to get this information
Similar to the method in UIViewController
-(void)viewWillAppear;
Would like something like
-(void)UIViewWillAppear;
Edit for some comments I saw:
I'll explain a bit more
But I have a special case where the UIView needed to add a "floating view" on top of itself (Imagine a zooming/panning/scrolling UISCrollView subclass with floater on top of itself) such that when it scrolled the floating view stayed in place relative to the superview. I tried recalculating the new origin of the "floater" inside of the -(void)layoutSubviews method but the re-placement was very choppy. In order to solve this choppyness problem, the custom UIView added the floating view (which in theory is its subview) as a subview for its superview (a bit of a tongue twister :) ).
Now arises a problem when the custom UIView is removed (or its containing view controller is pushed offscreen). How can the special UISCrollView remove the floating view from its superView.
You can override willMoveToSuperview: to find out when a view is inserted into a hierarchy and when it's removed. That's probably not what you want since the view can be part of a hierarchy and not be inserted by itself.
To find out if it's on screen use willMoveToWindow:. If the argument is non-nil the view just became part of a visible view hierarchy.
If you need to do something after the change use didMoveToWindow:.
UIView do not appear/disappear 'randomly' or when they want - your view controllers (or code) control this. So you should find out when you show them, and call code you need.
The UIView class reference has some kvo observing change.
By implementing -(void)willRemoveSubview:(UIView *)subview you could see the other way round.
UPDATE After reading the explanations:
I hope I understood correctly. I did something similiar time ago, but with a UITableView rather than a UIScrollView (but they are quite the same underneath).
It was like a popup detail view. I solved, as you already did, by adding the detail view to the UITableView superview, and then I added a close UIButton in the detail view, with a corresponding IBOutlet:
#interface CustomUIView : UIView
#property(nonatomic,weak) IBOutlet UIButtonView *closingButton;
-(void)closeDetail:(IBAction)action;
#end
and the action was just:
-(void)closeDetail:(IBAction)action {
// do your cleaning/change to the detail subviews
[self removeFromSuperview]; // <-- clsoe the detail view
}
sdsds
I'm trying to add a UIView on top over the UITableView to mimic the iPhone Facebook style menu. I have it working fine by making the controller a UIViewController then adding a tableview however I am unable to make the menu a static menu unless the controller is a UITableView.
Is it possible to add a view ontop of a tableview and only make the tableview in the background scrollable without the view in the foreground scrolling?
Here is what I have with the subclass being UIViewController
But I am unable to make the tableview cells static via IB since it is not a subclass of UITableView Controller.
EDIT per NSJones Code:
It seems to be going somewhat in the right track. However the view still blocks the table. If I remove the view from the storyboard it will only display the table.
You can make a view hover the same way you make any real thing hover; Hold it up with something invisible.
Basically what you want to do is create a clear UIView (with user interaction disabled) that is the size of your view controller's view, and add it as a subview to your view controller's view property. That way it sits invisibly on top. then you can add a subview to that clear view and that subview won't move.
Edit:
It seems this nice clean approach won't work for you since you need your view controller to be a UITableViewController. The answer for this slightly more complex approach is to use a delegate method for UIScrollView which also works for UITableView. Apple has a fantastic demo of this concept in the WWDC2011 - Session 125 - UITableView Changes, Tips, Tricks video. If you can watch it I highly recommend it. The meat of this issue begins at about 36:10.
But to sum it up you implement the scrollViewDidScroll: delegate method. And handle the movement of the tableview by adjusting the position properties of the view. Here I am keeping an UIView property named viewToKeepStill still using this method.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
// CGFloat stillViewDesiredOriginY; declared ivar
CGRect tableBounds = self.tableView.bounds; // gets content offset
CGRect frameForStillView = self.viewToKeepStill.frame;
frameForStillView.origin.y = tableBounds.origin.y + stillViewDesiredOriginY; // offsets the rects y origin by the content offset
self.viewToKeepStill.frame = frameForStillView; // set the frame to the new calculation
}
Instead of adding it as a subview of the table view, add it as a subview of the superview of the table view; that way it won't scroll.
So instead of this:
[tableView addSubview:viewController.view];
Do this:
[tableView.superview addSubview:viewController.view];
Assuming you want something that is visible full-time with the table, start with a view which contains both the menu view and the UITableView. Make the table smaller so it ends where the menu view begins. The table view can work with less vertical space.
If you have your UIViewController's view to be your table view then your table is going to span over the whole screen, so you won't be able to add anything on top of it.
Why not try the following:
1) create a new UIViewController
2) add a view on top where you want your menu
3) in the space left under just drag a table view from the component library
4) don't forget to set the 2 table view delegates to be your view controller class
that's about it?
I have a View in a xib file and a corresponding ViewController.
With Interface Builder I put an image, some labels and now a table view in it.
What I want to have, is that the whole view will be scrollable, because the new table view is currently only scrolling inside the tableview boundaries.
How can I put a scroll view behind this existing view with IB?
I already put a UIScrollView to the IB and put all other elements on it. Also I create an UIScrollView IBOutlet and connect it, but the screen is not scrollable...
Do I have to do something like
[myScrollView addSubview: ???];
Thank you a lot in advance & Best Regards.
You need to set the contentSize property of the scrollview before it is usable. Yeah, I know - freaking ridiculous that this isn't automatic.
Just do myScrollView.contentSize = CGSizeMake(int, int).
I have a beginner iPhone project going. I have a TableView, which is just a listbox with a bunch of entries and a small UiView on the bottom. See the pic.
The problem is that the UiView essentially becomes part of the listbox and will only appear when I scroll down to the last item in the TableView.
I'd like the UiView to be anchored on the bottom and never move. I've looked all around the Interface Builder and can't find anything (though in its defence I am a total noob to iPhone dev). How do I accomplish a trick like this?
alt text http://www.sqleffects.com/mystuff/ibissue.jpg
Ok, what you need is a UIView, that contains
an UIView, which acts as the TableViewController and thus has to implement the UITableViewDelegate and UITableViewDataSource protocols (but it MUST NOT be derived from UITableViewController directly, since by doing so the UITableView will automatically take up the whole screen size (except toolbars, navbars and/or tabbars))
another UIView, the one you would like to place at the bottom
by doing so, you can create an UITableView in IB (not an UITableViewController!) and connect it with the UITableView property in your UIView (the one mentioned in 1.)
using this method it is possible to give the UITableView a fixed size (which you'll need to, to have room at the bottom for your second UIView)
To build off gabtub's answer, the UIView containing your table view and your bottom view doesn't need to implement the UITableViewDelegate and UITableViewDataSource methods.
Since it sounds like you're building with a view controller, I'd make your main view controller a subclass of UIViewController (instead of using UITableViewController). You could then add your UITableView and your UIView the the UIViewController's view instance.
I'd then make your UIViewController subclass implement the UITableViewDelegate and UITableViewDataSource protocols - you'll end up with something that looks similar (code-wise) to your old UITableViewController subclass, but it's view property will be the underlying UIView instead of UITableView instance (if you poke around in the debugger, you can see the [UITableViewController view] and [UITableViewController tableView] return the same object)
One of the advantages over gabtub's suggestion is it saves you from creating a one-off UIView subclass, since you've probably already got a one-off UIViewController subclass (or, previously had a one-off UITableViewController subclass).
The problem is probably, that right now, the UIView is a section footer view, and is therefore contained within the table view.
If you delete the UIView from the TableView, scale the TableView to make space for the UIView and a bit more and put your UIView where you want it, it probably will be added to the TableView's superview. You can then resize the TableView to the correct size.
The bottom line is this: if you create your project based on the Navigation template, you can't resize the UiTableView, period.
So to do what I want, I basically have to start from scratch and pick a View or Window based template and drop the UiTableView on it manually.
My navigation-based-app's background looks like a paper on a cork bulletin board. My RootViewController is, of course, an UITableView. I want to have the TableView end on the paper and not on the cork. Some pictures here to explain it better:
alt text http://img528.imageshack.us/img528/3469/bildschirmfoto20091028u.png
This is how it looks when I scroll to the last row of the TableView. For this, I'm using the "Inset" property for "Content-Bottom" and "Scrollers-Bottom" in Interface Builder.
alt text http://img24.imageshack.us/img24/3469/bildschirmfoto20091028u.png
This is how it looks when I scroll to the top of the TableView.
alt text http://img28.imageshack.us/img28/64/35859544.png
And this is how I want the TableView to look when I scroll to the top.
How can I do this?
Thanks a lot ;-)
Yassin
You can make frame of your tableView with the smaller size.height parameter. It will do the trick.
Oh... Ok. I have no mac nearby right now so I don't want to post much code. I will try to explain. First of all, you should inherit your rootViewController from UIViewController, not UITableViewController. If you are using IB, you have to refer your main view to your RootViewController's view property. Then you can set background of you main view
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"myImage.png"]]];
or add a UIImageView to your view and set your background image there. Then you have to add a UITableView to your view and set it's frame at any size you want. Next step - to refer your new tableView to the outlet inside your class. Smth like that:
IBOutlet UITableView* myTableView;
in your viewDidLoad: method set your new tableView's background to clearColor
[myTableView setBackgroundColor:[UIColor clearColor]];
and the last one. all your self.tableView you have to replace with myTableView.
P.S. Oh, don't forget that your new tableView should has frame with x,y,width properties, identical to your self.view's ones and tableView's height property should be a bit smaller.
Or just use insertSubview:corkBoard atIndex:1 during viewDidLoad or whatever. The corkBoard name should be whichever view the cork board is on, and index counts how many views are below it. So 1 would be only one view underneath, the UITableView. Make sense? Of course if you have more views you want underneath it, just change the index count.
In my opinion, this works better than setting a frame. The frame would have an awkward whitespace below it, while this just puts the table behind the cork. Quite ingenious :)