I am currently using this code:
FlipView *fv = [[FlipView alloc]init];
[UIView transitionWithView:flipContainer
duration:1
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[flipContainer addSubview:fv];
}
completion:NULL];
to flip a container view containing a UIImage around to reveal a second view (FlipView). FlipView is a UIView currently with its background set to red for debugging.
What happens now is that the container flips, but it's displaying the same thing as before, despite using:
[flipContainer addSubview:fv];
What am I doing wrong?
What happens if you add the subview without the animation? Does the subview appear? Maybe the subview isn't being initialized properly (such as maybe its frame isn't being set properly?)
You could try initializing like this:
CGRect frame = CGRectMake(xOrigin,yOrigin,width,height);
FlipView *fv = [[FlipView alloc] initWithFrame:frame];
Or try setting the frame property of the FlipView:
FlipView *fv = [[FlipView alloc]init];
CGRect frame = CGRectMake(xOrigin,yOrigin,width,height);
fv.frame = frame;
Related
I'm trying to have my collectionview cell/uiimageview go full screen when the image is tapped. I'm using animation and doing this from didSelectItemAtIndexPath and everything works and looks great, except that the imageview does not change size at all, and obviously is not going full screen like I want. I can see the animation working, however it all happens within the cell's preexisting size, and therefore, the image gets cropped. I would like it go full screen when tapped, similarly to the way it works in FB when tapping a photo. Appreciate any help! Here's my code...
#interface BaseViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UITextFieldDelegate> {
CGRect prevFrame;
}
#property (nonatomic) BOOL isFullScreen;
- (void)updateUI;
#end
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ImageViewCell *selectedCell = (ImageViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
NSLog(#"didSelectItemAtIndexPath");
if (!self.isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
NSLog(#"starting animiation!");
prevFrame = selectedCell.imageView.frame;
selectedCell.imageView.center = self.view.center;
selectedCell.imageView.backgroundColor = [UIColor blackColor];
//[selectedCell.imageView setFrame:[[UIScreen mainScreen] bounds]];
[selectedCell.imageView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}completion:^(BOOL finished){
self.isFullScreen = YES;
}];
return;
} else {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[selectedCell.imageView setFrame:prevFrame];
selectedCell.imageView.backgroundColor = [UIColor colorWithRed:0.62 green:0.651 blue:0.686 alpha:1];
}completion:^(BOOL finished){
self.isFullScreen = NO;
}];
return;
}
}
Your view cell is embedded in a view hierarchy, and most views clip their sub-views. To get a "full-screen" effect you're going to need to either (a) set parent views of your image view (the cell, the collectionView, anything that might be embedded in, etc) not not clip subviews (see: "clips to bounds") or (b) put your image in a view that is not embedded in those containers.
I don't recommend (a). Trying to set containers to allow child-views (your UIImageView) that are bigger than the container is kind of an anti-pattern that breaks the idea that containers manage and contain the display of their children.
For (b), what you would want to do is:
on Tap:
imageView = << create a new UIImageView >>
[self.view addSubview:imageView]
set imageView.image = collectionCell.imageView.image
set imageView.frame = << translated rect of the collectionCell.imageView.frame >>
... animate blowing your new imageView up to full-screen...
So you're basically treating the "tap on cell" action as a command to "create a new UIImageView to show the image, and animate that to full-screen."
Since the new image view is a direct child of the VC's root view, it can be sized full-screen without getting clipped by a parent view.
Does anyone know how to achieve the present view controller's view to shrink and put another one over it with a transparency? It is achieved in Tweetbot 3 when you tap on your avatar in the top left on the navigation bar. Should I take a snapshot for example?
In order to achieve this effect you will have to rebuild your view stack from scratch.
So as there is no possibility to change the viewController.view's frame, you'll have to add a kind of container subview a little like this:
#implementation ViewController
#synthesize container;
- (void)viewDidLoad {
[super viewDidLoad];
container = [[UIView alloc] initWithFrame:self.view.frame];
[self.view addSubview:container];
// add all views later to this insted of self.view
// continue viewDidLoad setup
}
Now if you have that, you can animate the shrinking behavior like so:
[UIView animateWithDuration:.5 animations:^{
container.frame = CGRectMake(10, 17, self.view.frame.size.width-20, self.view.frame.size.height-34);
}];
Okay, I assume you are developing for iOS 7, so we'll make use of some new APIs here (for earlier versions there are alternative frameworks). Now since WWDC UIView's got a resizableSnapshotViewFromRect:(CGRect) afterScreenUpdates:(BOOL) withCapInsets:(UIEdgeInsets) method returning a single UIView object.
[UIView animateWithDuration:.5 animations:^{
container.frame = CGRectMake(10, 17, self.view.frame.size.width-20, self.view.frame.size.height-34);
} completion:^(BOOL finished) {
UIView *viewToBlur = [self.view resizableSnapshotViewFromRect:container.frame afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
}];
If you do not want to rewrite your view management, you can also first take a snapshot of your main view this way, set it to the container and then animate only the image. But remember, you can not interact with the captured view then.
When you've got that, you can download the two category files from this repo (They're from WWDC, so directly from Apple!). Basically, what they do is, they add some cool new methods to the UIView class, of which we'll use applyDarkEffect. I haven't tested this, maybe another method fits your needs better here.
Anyways if we implement that into the block and maybe also add a UIImageView to display the blurred overlay, it should look something like this:
[UIView animateWithDuration:.5 animations:^{
container.frame = CGRectMake(10, 17, self.view.frame.size.width-20, self.view.frame.size.height-34);
} completion:^(BOOL finished) {
UIView *viewToBlur = [self.view resizableSnapshotViewFromRect:container.frame afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
UIImage *image = [viewToBlur applyDarkEffect];
UIImageView *blurredView = [[UIImageView alloc] initWithFrame:self.view.frame];
[self.view addSubview:blurredView];
// optionally also animate this, to achieve an even smoother effect
[blurredView setImage:image];
}];
You can then add your SecondViewController's view on top of the stack, so that it's delegate methods will still be called. The bounce effect of the incoming account view can be achieved via the new UIView animation method animateWithDuration:(NSTimeInterval) delay:(NSTimeInterval) usingSpringWithDamping:(CGFloat) initialSpringVelocity:(CGFloat) options:(UIViewAnimationOptions) animations:^(void)animations completion:^(BOOL finished)completion (more on that in the documentation)
I hope that will help you with your project.
I got this warning:
'UIView' may not respond to 'addSubview:withAnimation:'
The line of code which produce that warning is this:
[self.masterView addSubview:self.detailImage withAnimation:def];
And my relevant code is like this:
ExUIViewAnimationDefinition *def = [[ExUIViewAnimationDefinition alloc] init];
def.type = ExUIAnimationTypeTransition;
def.direction = ExUIAnimationDirectionMoveUp;
[self.masterView addSubview:self.detailImage withAnimation:def];
[def release];
I looked on the UIView documentation, i thought addSubview may be deprecated, but it still like this.
Does any one know how to solve this warning? Thanx in advance.
addSubview is a method UIView will respond to. addSubview:withAnimation: is not a method UIView will respond to.
If you want to add a subview with a fade or something like that, try this:
self.detailImage.alpha = 0.0;
[self.masterView addSubview:self.detailImage];
[UIView animateWithDuration:0.3 animations:^{
self.detailImage.alpha = 1.0;
}];
To add a subview to a parent, call the addSubview: method of the parent view. This method adds the subview to the end of the parent’s list of subviews.
To insert a subview in the middle of the parent’s list of subviews, call any of the insertSubview:... methods of the parent view. Inserting a subview in the middle of the list visually places that view behind any views that come later in the list.
[self.masterView addSubView:self.def];
[def release];
This helped me to animate subview by sliding out from down of border of parent view
-(void) addAnimatadView:(UIView *) animatedView toView:(UIView *)aView {
CGRect frame = animatedView.frame;
float origin = frame.origin.y;
frame.origin.y = aView.frame.size.height;
[animatedView setFrame:frame];
[aView addSubview:animatedView];
frame.origin.y = origin;
[UIView animateWithDuration:0.4 animations:^{[animatedView setFrame:frame];}];
}
Just change frame origins as you want to reach free sliding
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.
I have a simple UIView animation block. In the block, I only change the view's alpha, but the view's frame is also being animated! WTF?
Here's my code:
UIButton *button = [flowerViews objectAtIndex:index];
UIImageView *newGlowView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"grid_glow.png"]];
newGlowView.frame = CGRectMake(0, 0, 130, 130);
newGlowView.center = button.center;
newGlowView.alpha = 0.0;
[scrollView_ addSubview:newGlowView];
[scrollView_ sendSubviewToBack:newGlowView];
[UIView animateWithDuration:0.3 animations:^{
newGlowView.alpha = 1.0;
}];
As you see, I'm creating a new view and adding it to scrollView_. I'm setting the view's position and alpha before adding it to scrollView_. Once it's added, I have an animation block to animate the view's alpha from 0 to 1.
The problem is, the view's position is also being animated! As it fades in, it looks as if it's animating from an original frame of CGRectZero to the one I've assigned it.
Ostensibly, only properties set within the animation block should be animated, right? Is this a bug? Am I missing something?
Thanks!
Perhaps the whole thing being called from an animation block or maybe within an event that is within an animation block like the autorotate view controller delegate methods.