determine if uiview is displayed - iphone

is there a possibility to determine if an uiview obj is going to be displayed. imagine: you have 2 uiviews in an uiscrollview. now you are going to switch per gesture from the first view to the second. the first view now is NOT in the viewport. now you are going to go back to the first view. and now I want to be notified that this view is in viewport, or is redisplayed. the same has to be for the second view. I have not found any callback or something like this.

You make sure your UiViewController overrides viewWillAppear: (before it appears this method is called) or viewDidAppear: (after this method is called).
See: http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/viewWillAppear:

That depends what you mean by "switch". If one view is just scrolled out of the visible area of the scrollview, but still remains attached as a subview to it, then you may want to check if the bounds of your view overlap those of the scrollviews visible area.
You could do this by using UIScrollView Delegate's scrollViewDidScroll: method to implement a check for overlaps while the user is scrolling.
If however your view is actually removed from the viewstack, then you may want to subclass UIView and implement willMoveToSuperview: to check if the view has been added to the scrollview again.

Related

UICollectionView delegate is not responding when the UICollectionView is embedded within a UIScrollView

I have a UIViewController with a UIScrollView. The top half of the screen contains some labels and text fields. The lower half of the screen is the UICollectionView. The UICollectionView is embedded within the scrollview so that when the user scrolls down they are not limited to a half screen size collection view.
The collection view is presenting properly and the delegate is set as I've done countless times before.
I've purposely tested different solutions and if the collection view is added 'directly' to the UIViewController the didSelectItemAtIndex delegate method is called. When the collection view is added to a scrollView within the ViewController I get no response from the delegate method.
I have checked the Debug View Heirarchy and the ScrollView content size is sufficient to house the entire collectionView. The Debug view also shows the correct view as the UICollectionViewDelegate.
Any help would be appreciated.
Having written the question I worked out my issue.
As part of the layout within the first half of the screen, I have a UITapGestureRecognizer added to the UIScrollView to endEditing() should the user click outside of a UITextField. This tap gesture was receiving the tap and 'ending it' before it was passed to the UICollectionView.

Can a UIView know when it is on screen

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

Is it possible to avoid SuperViews when hitTesting?

Basically, I want to be able to click all the Subviews in the Image below...
I want to be able to tap the Subviews of View B but View A is in the way even though View A Subviews are not blocking the views below. Is this possible? In other words I want to be able to tap through the transparent parts of a view even though its frame/bounds cover that area. View B is under View A in a ScrollView.
thanks,
austin
The solution is to subclass View A (if it's not a custom view already) and override pointInside:withEvent.
Return YES if the specified point is inside one of View A's sub-views, or NO otherwise. When pointInside:withEvent returns NO the system will continue to try other views until it finds one that claims the point is inside it, then it will call hitTest:withEvent to see which inner-view to send the touches to (the default behaviour).

iOS: Add UIView to UITableView

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?

How to resize other subviews and parent view when one subview size changes

I have a view which is similar to mail app. I have a scroll view and in that many other subviews. When the user clicks on any textview, it expands to show the text in it. e.g. "to" field in mail. I would want to resize the other subviews such that it starts below the expanded region. How can I do that.
I created the view through IB and I marked it for flexible top margin to facilitate this. But nothing happens automatically and hence I was wondering if I need to call sizethatFits/setneedsLayout.
When the subview resizes, call [[self superview] setNeedsLayout]. In your superview, implement -layoutSubviews to do the actual layout. You'll have to calculate everything yourself. Fixed/flexible margins are relevant to resizing the superview, not on peer views. The default -layoutSubviews does nothing at all; it just gets called at appropriate times.
If you need to force layout to happen at a particular point, then you can call -layoutIfNeeded on yourself or your superview. Read the docs on how this method works. Generally speaking you don't need to call this, though. It will usually get called at the appropriate time if you just use -setNeedsLayout.