Is this possible? Basically, I want to give my UIView a subview, and have that subview be in front of the view's layer (more specifically, in front of said layer's border).
Of course I could achieve the effect I want by making two subviews of the view's superview, one on top of the other. But I'd rather avoid that if possible.
I looked for this for a while myself; i don't believe it is possible. I solved the issue by, as you hint at, adding the subview and the parent to the same 'container' superview. Then its just a matter of ordering the two subviews, so that your subview is above the other and its border.
I solved this with a segue animation where i needed the sourceViewController to be in front of the destinationViewController. I had to remove the sourceViewController in order to re-nest it. My code looks like this:
- (void) perform {
UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;
UIView *parent = sourceViewController.view.superview;
[sourceViewController.view removeFromSuperview];
[parent addSubview: destinationViewController.view];
[parent addSubview:sourceViewController.view];
// Perform animation stuffs...
}
Related
I have a UISegmentedController i have 3 UIViewControllers Like photos,frames,gallery.
I add those 3 Views in Superview Using 'addSubView'. In frames view i have added a subview that name as EditView. In EditView i have done some changes, i want to update these changes in frames view. But when am removing EditView from frames view any single method doesn't calling. Then how to update the changes from subview in superview. Tree: UISegmentedController -> Frames(Su) -> EditViews(Subview). Can any one help me..
I found the code to update something in superview from subview. Please use this code in your subview. It will call your superview viewWillAppear method. You can use another method instead of viewWillAppear. It works for me.
for (UIView* next = [self.view superview]; next; next = next.superview)
{
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
{
[(UIViewController*)nextResponder viewWillAppear:YES];
}
}
-Yuva.M
You could access the super view of any UIView by using the superview property of UIView.
The below statement will be in your EditView.
FrameView* mySuperFrameView = (FrameView*)self.superview;
and the next statement could be calling the super view function.
[mySuperFrameView updateMySuperView];
updateMySuperView is the part of your superview.
Removing a view from its superview releases it.
Submit your changes before removing the editView from its superview. You could overwrite removeFromSuperview in your editView, and do your data manipulation before calling super removeFromSuperview.
Or your view controller could take data from the editView before removing it.
Here is a related question I found, but it does not answer my question in detail.
[http://stackoverflow.com/questions/3209993/cocoa-touch-can-i-have-multiple-views-per-view-controller-or-specify-bounds-of][1]
I have a UIView class, BallView, which is set to be the default view of the ballViewController. Now, this view has a ball bouncing around according to the accelerometer. I am calling a private function draw every time the accelerometer sends updates.
However, my main question is: I would like to have multiple such balls bouncing around.
Do I have to recreate the view for every class ? But then the File's Owner's IBOutlet view will also have to be connected. And an IBOutlet can point to just one address.
Any other way round this ?
Here is how I'm instantiating the Ball View class in the ballViewController:
[motionManager startAccelerometerUpdatesToQueue:queue withHandler:
^(CMAccelerometerData *accelerometerData, NSError *error){
[(BallView *)self.view setAcceleration:accelerometerData.acceleration];
[(BallView *)self.view performSelectorOnMainThread:#selector(draw) withObject:nil waitUntilDone:NO];
}];
Thus, it means, my question is a bit different from those multi-view tab-bar solutions. Because in those cases only 1 view is shown at a time. I want 4-5 views overlaid on top of each other.
Any help ?
You're right, your view controller can only have a single UIView in its view property. That view though can certainly be used to contain other subviews.
What I would do is have a plain old UIView as your controller's view, and have your BallViews be subviews of that view. Your controller can still control those views, they ust can't all be in its view property.
EDIT: If you're using nib files/Interface Builder, adding a BallView as a subview of your controller's view is pretty easy - just drag a UIView object onto the view, and in the identity inspector you can change the identity of the view to your BallView class.
If you're not using IB, you can also do the same programatically:
// BallViewController.h
#interface BallViewController
{
BallView* ballView;
}
#end
// BallViewController.m
#implementation BallViewController
- (void) loadView
{
...
CGRect frame1 = ...
CGRect frame2 = ...
self.view = [[UIView alloc] initWithFrame:frame1];
ballView = [[BallView alloc] initWithFrame:frame2] retain];
[self.view addSubview:ballView];
...
}
#end
I have UILabels animating on my mainView and I want to have a custom UIView pop onto the main view when a button is pressed. The labels animating in the background continue to animate and the problem that I'm having is that the labels animate on top of my custom UIView.
Does anyone know how I can ensure that my custom UIView is the front-most view so that the UILabels animate behind it?
You may want to look at
- (void)bringSubviewToFront:(UIView *)view
in the parent view.
#implementation UIView (moveToFront)
- (void) moveToFront { [[self superview] bringSubviewToFront:self]; }
#end
When I add a subview to my UITableViewController, it seems to be underneath the tableview. I may be loading my subview incorrectly, or calling addSubview in the wrong place. The subview I'm referring to is the red area above the tabbar that also contains the "Click me" button:
You can see that the cell lines kind of overlap. Here is where I'm adding the subview in my TableViewController:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect hRect = CGRectMake(0, 170, 320, 480);
HomeScreenOverlayView *homeView = [[HomeScreenOverlayView alloc] initWithFrame:hRect];
[self.tableView addSubview:homeView];
[homeView release];
}
Any ideas? Thanks!
I have had this issue myself and resolved it by not adding a view to the table, but rather adding the view to the table's superview.
UIView *viewToAdd = [[UIView alloc] initWithFrame: self.view.frame];
[self.view.superview addSubview: viewToAdd];
This is particularly useful when you want to mask the entire table (e.g. loading screens).
N.B. I will usually add this to viewWillAppear: in the view's lifecycle.
When you call addSubview, it is probably the first view added to the table view. Later, all the cells and support views will be added over your view.
The best thing to do is create an empty view and add both the table view and overlay view to it, making sure the overlay view is above the table view.
Views serve the 3 roles of drawing, interaction and layout. It is fine to have a view that only fills one of those roles.
You can use - (void)sendSubviewToBack:(UIView *)view or - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index. addSubview always puts the new view in front.
EDIT: Sorry, misread the question, it looks like you want the subview to be in front.
I have a question about UIViewController's subview, I created a UIView subclass MainView, which has the exact size of the screen, I wonder which is a better way of adding MainView, consider the following factors:
1 As MainView has same size as the whole screen, the MainView itself may have subviews, but there is no views at the save level as MainView(ie I don't need to add other subviews to self.view).
2 If I use self.view = mainView, do I put the code in loadView(as the viewDidLoad method means the view(self.view) is already loaded)? I see the loadView method is commented out by default, if I add the code to this method, what other code do I need to put together(e.g. initialize other aspects of the application)?
3 If I add mainView via [self addSubview:mainView], are there actually two off screen buffer? One for self.view, one for mainView, both has same size as the screen and one is layered on top of the other(so it wastes memory)?
Thanks a lot!
I'm not sure I completely understand what you're asking, but I'll try to answer a few of the questions you have.
First of all, if you have multiple UIViews on the screen they are all loaded into memory. You have to do -removeFromSuperview and release them to get the memory back.
You can assign your UIView as the UIViewController's view. For example:
MainView *mainView = [[MainView alloc] initWithFrame:CGRectMake(320.0, 480.0)];
self.view = mainView;
[mainView release]; //since the .view property is a retained property
in that case, you have have the view's initialization code in the -init method. Just redefine it like:
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
//initializations
}
return self;
}
You must implement loadView if you did initialize your view controller with a NIB.
UIViewController takes care of sizing its "main" view appropriately. This is all you need to do:
- (void)loadView
{
UIView* mainView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
self.view = mainView;
}
I'd solve all of this by doing it in a xib! If you create a UIView in your xib, you can then change it's class (when you select the UIView there should be a text field in the Class Identity section of the Identity inspector* - type 'MainView' here!)
Then, create your view controller by calling
myViewController = [[MainViewController alloc] initWithNibName:#"MyNibName" bundle:nil];
That should solve your problems; it's the main subview of your view controller (directly accessable from self.view) and you don't need to worry about memory usage, there's only one view :)
Sam
NB * Click tools -> Identity Inspector. I didn't know it was called this until I had to write this answer!
Yes, the first code-snippet shown above is the "standard" approach, AFAIK, when not using (evil!) NIB files -- i.e. when alloc'ing your view in-code, via loadView.
Note it seems one can also get away with the following, instead of hard-coding the screen-rect size:
UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.view = myView;
[myView release];
Note you definitely want to do the [myView release] call since, indeed, as pointed out above, self.view (for UIView) is a retained property.
Cheers, -dk
Perhaps the most important thing to do is make sure you have the following:
self.view.userInteractionEnabled = YES;
While it might not be required all of the time, it fixes the issue where self.view is unresponsive. This issue pops up occasionally.