UIScrollView loses 'bounce' effect without any reason - ios

I created an app for iPad which lets you navigare through some presentations... there are two views: The list of presentations and the view which shows you the presentation.
When a user selects a presentation (in PresentationListController), I show the presentation in the other view (PresentationViewController).
The PresentationViewController contains a UIScrollView with a list of pages... the problem is that after some time, without a recurring event which causes this problem, the UIScrollView 'loses' its capacity to bounce... so the scrolling is not smooth and it's like scrolling a rigid view without that fancy bounce effect... The user is still able to scroll but the effect is very ugly. The problem is that, the problem remains even if I go back the the PresentationListController and select a new PresentationViewController... the new presentation which is shown, have this problem.
I thought it was due to the fact that the navigationcontroller kept the UIView in memory and reused it whenever I opened a new presentation, but this is not the case because I debugged and saw that when I change the presentation, the dealloc method is called on the PresentationViewController.
So, how can I manage this problem?
EDIT
I found how to reproduce it: I am doing an animiation to open the list of pages, and an animation to close it. When I open a presentation which contains lots of pages (so that the contentSize of the UIScrollView > the width of the UIScrollView), I get no problem. But When I open and close the pages list in a presentation which only has one page, the problem begins. I wrote the code I am using to perform the animation+
here is the code I am using to perform the animation which opens and closes the pages list:
- (IBAction)showPagesView:(id)sender {
if (pagesListVisible) {
[self resetNavigationControls];
} else {
[self resetNavigationControls];
scvPages.frame = CGRectMake(0, 960, 768, 0);
scvPages.alpha = 0.0f;
[btnPages setImage:[UIImage imageNamed:#"thumbON.png"] forState:UIControlStateNormal];
[UIView animateWithDuration:0.7 animations:^{
scvPages.frame = CGRectMake(0, 760, 768, 200);
scvPages.alpha = 1.0f;
pagesListVisible = YES;
} completion:^(BOOL finished) {
if (finished) {
scvPages.contentSize = scvPages_ContentSize;
}
}];
}
}
Here is the method I use to hide the pages list (and other views)
- (void)resetNavigationControls {
if (pagesListVisible) {
[btnPages setImage:[UIImage imageNamed:#"thumb.png"] forState:UIControlStateNormal];
hidePages = YES;
// Nascondi la lista delle pagine.
[UIView animateWithDuration:0.7
animations:^
{
scvPages.frame = CGRectMake(0, 960, 768, 0);
scvPages.alpha = 0.0f;
}
completion:^(BOOL finished)
{
if (finished) {
scvPages.contentSize = scvPages_ContentSize;
pagesListVisible = NO;
}
}
];
}
}
Hope it helps. Thank you.

If I had to bet, it would be on your scrollview being zoomed and not resetting the affine transform back to the identity. I'm no expert on such things, but that's where I would look.
If your scrollview isn't zooming at all, then I'd recommend logging the values of scrollview.bounces, .bouncesZoom, .alwaysBounceVertical and .alwaysBounceHorizontal on a timer from the beginning of your app and see if anything changes the values while triggering your bug. You want all to be YES all the time, of course.
Good luck,
Damien

Related

IOS/Objective-C: Slide updated view in from right on swipe

I would like to emulate the swipe to left to show next picture seen in the photos app, among other places so that the new picture slides in from right to left using animation.
However, in my case, the view has more than one photo. It has a caption as well.
I am able to do this without animation by just updating the photo and text upon swipe. This just changes the photo and caption on screen, however, without the right to left animation technique.
Is there a way to show the old view moving to the left while the new updated view moves in from the right.
The following moves the view to the left but renders the screen black as nothing is put in its place.
//In handleSwipe called by gesture recognizer
CGRect topFrame = self.view.frame;
topFrame.origin.x = -320;
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.view.frame = topFrame; _myImage=newImage;
_mycaption=newcaption;} completion:^(BOOL finished){ }];
Thanks for any suggestions.
Edit:
The view in question is a detail view that you get to from a tableview through a segue. It currently already uses a scrollview for vertical scrolling as the content can exceed a single screen in the vertical dimension.
I have found a way to get the old photo and caption to move left and the new to come in from right using a completion block, however, it is less than satisfactory, because there is a gap between the two actions when the screen is black. This seems endemic to completion approach because new image does not start to move until old image has completed moving.
- (IBAction)swipedLeft:(id)sender
{
CGRect initialViewFrame = self.view.frame;
CGRect movedToLeftViewFrame = CGRectMake(initialViewFrame.origin.x - 375, initialViewFrame.origin.y, initialViewFrame.size.width, initialViewFrame.size.height);
CGRect movedToRightViewFrame = CGRectMake(initialViewFrame.origin.x + 375, initialViewFrame.origin.y, initialViewFrame.size.width, initialViewFrame.size.height);
[UIView animateWithDuration:0.1
animations:^{self.view.frame = movedToLeftViewFrame;
//above moves old image out of view.
}
completion:^(BOOL finished)
{
self.view.frame = movedToRightViewFrame;
[self loadNextItem];//changes pic and text.
[UIView animateWithDuration:0.1
animations:^{self.view.frame = initialViewFrame;
//moves new one in
}
completion:nil];
}];
}
I suggest using a UIPageViewController, and manage each image/set of images as a separate view controller.
A page view controller supports either a page curl style transition or a slide transition. You'd want the slide transition.
Three ways to build this using existing components:
UIPageViewController (see DuncanC's answer).
UICollectionView with pagingEnabled set to true. Use a full-screen-sized cell and a UICollectionViewFlowLayout with scrollDirection set to horizontal.
UICollectionView as above, but instead of setting pagingEnabled to true, implement scrollViewWillEndDragging:withVelocity:targetContentOffset: in your delegate. This allows you to have a gutter between each cell while still having each cell fill the screen. See this answer.
It's ScrollView+PageControl
I hope it can help you.
- (void)viewDidLoad {
    [super viewDidLoad];
    self.scrollView = [[UIScrollView alloc] init];
    self.scrollView.delegate =self;
    self.scrollView.translatesAutoresizingMaskIntoConstraints =NO;
    self.scrollView.pagingEnabled =YES;
 self.scrollView.contentSize =CGSizeMake(ViewWidth*VIewCount, ViewHeight);
    [self.view addSubview:self.scrollView];
 self.pageControl = [[UIPageControl alloc] init];
   self. pageControl.translatesAutoresizingMaskIntoConstraints =NO;
    [self.view addSubview:self.pageControl];
    self. pageControl.numberOfPages = VIewCount;
    self.pageControl.currentPage = 0;
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView
                                                           attribute:NSLayoutAttributeCenterX
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:self.view
                                                           attribute:NSLayoutAttributeCenterX
                                                          multiplier:1.0f
                                                            constant:0.0f]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"[self.scrollView(width)]"
                                                                     options:0
                                                                     metrics:#{#"width":#(ViewWidth)}
                                                                       views:NSDictionaryOfVariableBindings(self.scrollView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[self.scrollView(height)]"
                                                                      options:0
                                                                      metrics:#{#"height":#(HEIGHT_VIEW)}
                                                                        views:NSDictionaryOfVariableBindings(self.scrollView)]];
     
   
  
 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[_scrollView]-5-[pageControl(15)]"
                                                                      options:NSLayoutFormatAlignAllCenterX
                                                                      metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(self.scrollView, self.pageControl)]];
//[imgArr addObject:[UIImage imageNamed:...]];
    for (NSInteger index = 0; index<ViewCount; index++) {
        UIImageView *addSubview = [[UIImageView alloc] initWithFrame:CGRectMake(index*ViewWidth, 0, ViewWidth, ViewHeight)];
// addSubView.image = [imgArr objectAtIndex:index];
        [self.scrollView addSubview:addSubview];
    }
}
 
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    NSInteger currentOffset = scrollView.contentOffset.x;
    NSInteger index = currentOffset / ViewWidth;
     
    if (currentOffset % ViewWidth == 0) {
        pageControl.currentPage = index;
    }
}
 

UIButton not responding after animation

I would prefer first download the project from below link and then continue with question (only 36kb)
Download Link
At start what I have is like below.
When I click My Office button, I am calling action actionSeenButton which will print NSLog(#"actionSeenButton");
- (IBAction)actionSeenButton:(id)sender {
NSLog(#"actionSeenButton");
}
This works perfect.
When I click, Show hidden button, I am sliding view by 100 and showing the image and buttons that I have at the top, as shown in below image
Code used is
- (IBAction)showHiddenButton:(id)sender {
CGAffineTransform translation = CGAffineTransformIdentity;
translation = CGAffineTransformMakeTranslation(0, 100);
[UIView beginAnimations:nil context:nil];
self.view.transform = translation;
[UIView commitAnimations];
}
When I click this button, I am calling action actionHiddenButton which will print NSLog(#"actionHiddenButton");
- (IBAction)actionHiddenButton:(id)sender {
NSLog(#"actionHiddenButton");
}
BUT the problem is, when I click the new button that I see, action is not getting called.
Any idea why this is happening?
Note
When I move the top hidden button from y=-70 to y=170, action is getting called.
Sample project can be downloaded from here
What I wanted to implement is, showing three buttons (as menu) on the top in one line by moving view down.
verify that your button is not behind the frame of another view. even if the button is visable, if there is something covering it up it wont work. i don't have access to xcode at the moment but my guess is your view "stack" is prohibiting you from interacting with the button. a button is esentually a uiview and you can do all the same animations to buttons and labels that you can with views. your best bet is to leave the view in the background alone and just move your buttons. since your "hidden" button isn't part of your main "view" hiarchy thats where your problem is.
upon further investigation, your problem is related to auto-layout and making sure your button object stays in the view hierarchy. if you turn off auto-layout you will see where the problem is. when you animate the main view down the "hidden" button is off of the view and there for inactive. the easiest solution is to just animate the buttons. the next best solution closest to what you have is to add another view onto your "main view" and then put the buttons into that view. also why do you have that background image twice? why not just set the background color of your view to that same yellow?
I downloaded your project and it seems the translation you're making for self.view. So the actionHiddenButton is not in the frame.Its better to have the controls you want to animate in the separate view.
If you want to see the problem, after your view get transformed set clipsToBounds to YES. Like
self.view.transform = translation;
self.view.clipsToBounds = YES;
Yipeee!!! Below is how I did.
.h
Added new variable.
#property (retain, nonatomic) NSString *hideStatus;
.m
-(void) viewDidAppear:(BOOL)animated {
NSLog(#"viewDidAppear");
CGAffineTransform translation = CGAffineTransformIdentity;
translation = CGAffineTransformMakeTranslation(0, -100);
self.view.transform = translation;
self.view.clipsToBounds = YES;
[UIView commitAnimations];
self.view.frame = CGRectMake(0,-80,320,560);
hideStatus = #"hidden";
}
- (IBAction)showHiddenButton:(id)sender {
NSLog(#"hideStatus===%#", hideStatus);
CGAffineTransform translation = CGAffineTransformIdentity;
if ([hideStatus isEqualToString:#"hidden"]) {
translation = CGAffineTransformMakeTranslation(0, 0);
hideStatus = #"shown";
} else {
translation = CGAffineTransformMakeTranslation(0, -100);
hideStatus = #"hidden";
}
[UIView beginAnimations:nil context:nil];
self.view.transform = translation;
self.view.clipsToBounds = YES;
[UIView commitAnimations];
}
Attached is the sample project. You can download from here.

Weird behaviour happens when using UIView animate and CGAffineTransform

I created some animations in my project. Basically, I use UIView animate and CGAffineTransform, but a very strange thing happened and I have no idea. Hope someone can help me solve this problem. Thanks in advance.
This is the strange thing:
After the user clicks on a button, the button slides off screen and another two buttons slide on the screen (I just changed the center point of these buttons to achieve this animation). And, some time later, a view on the screen start shaking (I use CGAffineTransform to achieve this).
At this moment, the strange thing happens - the button that previous slid off screen show up at its original position again and the other two buttons disappear (No animation, just shows up and disappear).
The following is the related code,
1) Button slide off and slide in animation related code
- (IBAction)start:(id)sender
{
// 1. Slide in cancel and pause button
[UIView animateWithDuration:0.5f animations:^{
[startButton setCenter:CGPointMake(startButton.center.x + 300.0f, startButton.center.y)];
[cancelButton setCenter:CGPointMake(cancelButton.center.x + 300.0f, cancelButton.center.y)];
[pauseButton setCenter:CGPointMake(pauseButton.center.x + 300.0f, pauseButton.center.y)];
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"Move finished");
}
}];
}
2) The view shaking animation related code
- (void)shakeView:(UIView *)viewToShake
{
CGFloat t = 2.0;
CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, t, 0.0);
CGAffineTransform translateLeft = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, 0.0);
viewToShake.transform = translateLeft;
[UIView animateWithDuration:0.07 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:2.0];
viewToShake.transform = translateRight;
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
viewToShake.transform = CGAffineTransformIdentity;
} completion:nil];
}
}];
}
This isn't weird, it's a common problem with
auto layout. If you move UI elements by changing frames, then as soon as something else takes place that requires laying out views, the moved views will revert to the position defined by their constraints. To fix it, you either need to turn off auto layout, or do your animations by changing constraints not frames.
I have tried your code in my test project. The problem is probably because you are using Autolayout in your xib.
Please checking your xib file and uncheck the Autolayout property.

How would I create a status message that briefly appears "above" a UITableView (like UIRefreshControl)?

I'm trying supplement a UIRefreshControl with a UIView containing a message (statusMessageView) that appears "above" a UITableViewController after the app launches. This view will inform the user that the UITableViewController is already refreshed and does not need refreshing.
Here is a breakdown of what I am trying to accomplish:
The app is launched, the UITableViewController appears normal then scrolls down 44px to reveal statusMessageView (with a height of 44px).
statusMessageView stays visible for 2 seconds
The UITableViewController animates a scroll up to it's original position, effectively "tucking" statusMessageView away. (like UIRefreshControl, but animated with code)
Note: This statusMessageView will be used in conjunction with a UIRefreshControl, so it needs to "go away" after it is displayed so that the UIRefreshControl can be used normally
I have looked at other 3rd party "pull to refresh" controllers, but I think that is overkill due to the fact I am using UIRefreshControl
It seems like the other answers here are providing solutions for a notification that drops down below the UINavigationBar. If you're still looking for a solution that sits in the scrollview of the UITableView, then I would add a custom table header (not section header) to the table view.
Here are the rough steps necessary to accomplish this:
1. Create the initial header view on load
I typically use a UIViewController subclass that owns a UITableView instance variable (instead of using a UITableViewController), but you should be able to accomplish this with either set up. In your tableview set up code (probably in viewDidLoad), where you set things like backgroundColor, contentInset, separatorStyle, etc, create a UILabel that will become your header. Then set this UILabel to be the tableHeaderView of your tableView. Of course, if you're looking to make something a bit more complicated for this "notification section", feel free to make it a UIView with a nested UILabel + something else. So something like:
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 44.0f)];
headerLabel.backgroundColor = [UIColor clearColor]; // Just in case you have some fancy background/color in your table view
headerLabel.textAlignment = UITextAlignmentCenter;
headerLabel.font = ....
headerLabel.textColor = ....
headerLabel.text = #"You are an awesome user!";
self.tableView.tableHeaderView = headerLabel;
2. Set your tableview to load "normally" (ie. not show header)
Again, inside viewDidLoad, you need to set your tableview's contentOffset and alwaysBounceVertical properly to hide this header view on load. contentOffset set to the height of the header will start the tableview's y coordinate right below the header. alwaysBounceVertical set to YES will allow your tableview to behave correctly even if your tableview's contentsize is less than your screen size. So something like:
self.tableView.contentOffset = (CGPoint){0.0f, 44.0f};
self.tableView.alwaysBounceVertical = YES;
3. Add the slide down and slide away
Ok, now there are a couple of ways you can do this. On viewDidAppear, you can create a chained UIView animation where the first animation slides the tableview down (ie. sets contentOffset to {0.0f, 0.0f}) is delayed by one second and the second animation slides the tableview back up (ie. sets contentOffset to {0.0f, 44.0f}) is delayed by two seconds. Or you can use GCD and schedule the two animations as async + delayed blocks. Either way is fine (and there are probably two or three other good ways to accomplish this), but just to get the idea across... you can chain the animation like this:
__weak MyCustomViewController *me = self;
[UIView
animateWithDuration:0.4f
delay:1.0f
options:UIViewAnimationOptionAllowUserInteraction
animations:^
{
me.tableView.contentOffset = (CGPoint){0.0f, 0.0f};
}
completion:^(BOOL finished)
{
if (me.tableView)
{
[UIView
animateWithDuration:0.4f
delay:2.0f
options:UIViewAnimationOptionAllowUserInteraction
animations:^
{
me.tableView.contentOffset = (CGPoint){0.0f, 44.0f};
}
completion:^(BOOL finished)
{
if (me.tableView)
{
me.tableView.tableHeaderView = nil; // If you want to completely get rid of this notification header
me.tableView.contentOffset = (CGPoint){0.0f, 0.0f}; // I'm unsure if this will cause the tableview to jump... if it does, you can animate the headerview away instead of animating the tableview up to hide the header, then setting header to nil and reseting the contentOffset
// or
me.tableView.tableHeaderView.hidden = YES; // If you want to just hide the header
}
}];
}
}];
I wrote the sample code without testing any of it... hehe, so it probably won't work as it. But happy to help you flesh this out if you need more help! Good luck.
Update: Allowing user scrolling to cancel animation
I'm not too sure what you want the user interaction on the table to do to the animation. If you just want the animation to be canceled when the user starts scrolling, then I would use GCD (see code below). But I can see other ways you can have the animation work with user touch, so it depends on what you're looking for. In any case, let's say any user touch should disable the next scheduled animation then it could be achieved using two functions like:
- (void)scheduleShowHeaderAnimation
{
__weak MyCustomViewController *me = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0f * NSEC_PER_SEC), dispatch_get_main_queue(), ^ // Start animating after 1 sec delay
{
if (me.tableView) // Make sure the tableview is still around
{
if (! me.tableView.tracking && // Don't show animation if user has begun to touch contentview
! me.tableView.dragging && // Don't show animation if user has begun to drag contentview
! me.tableView.decelerating) // Don't show animation if dragging happened and scrollview is starting to decelerate
{
[UIView
animateWithDuration:0.4f
delay:0.0f
options:UIViewAnimationOptionAllowAnimatedContent // This will make sure user can interact with tableview while animation is going on
animations:^
{
me.tableView.contentOffset = (CGPoint){0.0f, 0.0f};
}
completion:^(BOOL finished)
{
[me scheduleHideHeaderAnimation];
}];
}
}
});
}
- (void)scheduleHideHeaderAnimation
{
__weak MyCustomViewController *me = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0f * NSEC_PER_SEC), dispatch_get_main_queue(), ^ // Start animating after 2 secs delay
{
if (me.tableView) // Make sure the tableview is still around
{
if (! me.tableView.tracking && // Don't show animation if user has begun to touch contentview
! me.tableView.dragging && // Don't show animation if user has begun to drag contentview
! me.tableView.decelerating) // Don't show animation if dragging happened and scrollview is starting to decelerate
{
[UIView
animateWithDuration:0.4f
delay:0.0f
options:UIViewAnimationOptionAllowAnimatedContent // This will make sure user can interact with tableview while animation is going on
animations:^
{
me.tableView.contentOffset = (CGPoint){0.0f, 44.0f};
}
completion:^(BOOL finished)
{
if (me.tableView)
{
me.tableView.tableHeaderView = nil; // If you want to completely get rid of this notification header
me.tableView.contentOffset = (CGPoint){0.0f, 0.0f}; // I'm unsure if this will cause the tableview to jump... if it does, you can animate the headerview away instead of animating the tableview up to hide the header, then setting header to nil and reseting the contentOffset
// or
me.tableView.tableHeaderView.hidden = YES; // If you want to just hide the header
}
}];
}
}
});
}
I would call scheduleShowHeaderAnimation in the viewDidAppear.
Then to support hiding the header when the user has already scrolled the tableview down, I would implement either - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate or - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView of UIScrollViewDelegate and add something like:
if (self.tableView.tableHeaderView != nil)
{
self.tableView.tableHeaderView = nil;
}
// or
if (self.tableView.tableHeaderView.hidden == NO)
{
self.tableView.tableHeaderView.hidden = YES;
}
If there's more complicated interactions you want to support, or if you want the animation to respond to the user touch in different ways, you might need to override other UIScrollViewDelegate methods and when the user begins to interact with the scrollview (which is the parent class of the table view), then change the behavior of the animation.
Does this get you closer to what you're looking for?
besides the answer of #Khawar , there is another choice:
https://github.com/toursprung/TSMessages
You can use following library for this purpose. You can set the autohide time duration as per your needs. You can also customise its appearance.
https://github.com/tciuro/NoticeView
It can be done in a very simple way: you just create and insert a subview into your refresh control:
- (void)viewDidLoad {
[super viewDidLoad];
...
UIView *smView = [self statusMessageView];
[self.refreshControl insertSubview: smView atIndex: 0];
// to show and hide the view inserted in refresh control
// With this transparent loader color even the middle area is not covered
// so you can have all the space to show your message
self.refreshControl.tintColor = [UIColor colorWithWhite:1.0 alpha:0.0];
[self.refreshControl beginRefreshing];
[self afterDelay: 2.0 performBlock: ^(){
[self.refreshControl endRefreshing];
// this delay is needed to prevent loader animation becoming visible
// while the refresh control is being hidden
[self afterDelay: 0.25 performBlock: ^(){
self.refreshControl.tintColor = nil;
});
});
...
}
-(void)afterDelay: (float)seconds performBlock: (void (^)())block {
dispatch_time_t popTime =
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(seconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), block);
}
-(UIView)statusMessageView {
...
return view;
}
View size you need is 320x43px (if it is higher the bottom of it will be visible with refresh control hidden), the middle area (approximately 35px) will be covered by the loader animation (but not when you initially show the message).
I use UIImageView to show application logo there (it's even simpler: see here).
I would probably prefer (as a user) not to see this message before I start pulling. When I start pulling I will see that no update is needed before refresh starts (it starts when you pull down approximately twice more than the height of this subview, so user will have time to see what's there and if refresh is needed). If there are unread items in the table (tweets, posts, whatever), you can show the number of unread items in that view.
But it's a matter of personal preference, the way it is done it seems to achieve exactly what you want in a very simple way. I tested, it all works.

Recreate the default pushViewController animation programmatically (without a navigation controller)

I want to create a View outside of the visible screen and push in it (like the default pushViewController animation), but I cannot create the UIView outside. I was trying this code here, but it doesn't work. The View gets always created and displayed in the current UIScreen bounds. That means instead of both views, the one to get pushed out and the one to get pushed in, only the view that goes out "moves", the new view just sits at it's place.
In the the .m of the view to show:
- (void)viewDidLoad
{
[super viewDidLoad];
// set the views frame off the screen
self.view.frame = CGRectMake(320, 0, 320, 460);
}
In the method that actually does the transition:
-(void)showOverview:(UIViewController *)sender //sender = mapviewController
{
NSLog(#"overview");
// current view (frame) = mapviewCOntroller.view
CGRect outFrame = self.view.frame;
if (!self.overviewViewController) {
self.overviewViewController = [[UCOverviewViewController alloc] init];
self.overviewViewController.transitionDelegate = self;
// create a new View for the overview
[self.overviewViewController.view setCenter:self.view.center];
[self.view.window addSubview:self.overviewViewController.view];
[self.view.window bringSubviewToFront:self.mapViewController.view];
}
CGRect inFrame = self.overviewViewController.view.frame;
outFrame.origin.x = outFrame.origin.x-outFrame.size.width;
inFrame.origin.x = self.view.frame.origin.x;
[UIView animateWithDuration:0.5f animations: ^{
[self.view setFrame:outFrame];
}];
}
EDIT: this is my final code, at least the important part. Now, the view thats currently visible gets slider off screen at the same time the off-screen view gets slide in.
-(void)showOverview
{
if (!self.overviewViewController) {
NSLog(#"OverviewViewController created!");
self.overviewViewController = [[UCOverviewViewController alloc] init];
self.overviewViewController.transitionDelegate = self;
// add the subView
[self.view addSubview:self.overviewViewController.view];
[self.view sendSubviewToBack:self.overviewViewController.view];
}
CGRect outFrame = self.mapViewController.view.frame;
CGRect inFrame = self.overviewViewController.view.frame;
outFrame.origin.x -= outFrame.size.width;
inFrame.origin.x = self.view.frame.origin.x;
self.isOverviewViewVisible = YES;
[UIView animateWithDuration:0.5f animations: ^{
[self.mapViewController.view setFrame:outFrame];
[self.overviewViewController.view setFrame:inFrame];
}];
}
your problem is this line.
self.overviewView = self.overviewViewController.view;
You're overriding the view you created with the view you already have.
the following is not a great way to do it but it should work with what I think you have.
- (void)viewDidLoad {
self.overviewViewController.view.frame = CGRectMake(320, 0, 320, 460);
self.overviewViewController.view.backgroundColor = [UIColor blueColor];
}
Then you want another action to do the animations.
[UIView animateWithDuration:0.5f animations: ^{
self.overviewViewController.view.frame = CGRectMake(0,0,320,460);
}];
There are weird and incorrect things in your code that make it confusing to understand what is actually going on, but... forget about using the window anywhere. The only thing you need to worry about, is this. Say View A is your main view. View B is the view you want outside and to come in over A. Then, create B either from nib or manually, add it as a subview to view A, and before you enter the animation block to move it into place, make sure that the current frame is set to {ViewA.bounds.size.width, 0, ViewB.bounds.size.width, ViewB.bounds.size.height}. Assuming you want it to come in from the top right.

Resources