Subclassed UIView not displaying proper after animating frame - ios

I have subclassed UIView to contain basically a UIPickerView and a UIToolbar.
When the user selects a particular row in the picker I will then add a UIImageView over the picker. However this image is not visible when I have animated my UIView to slide up the screen. If I don't animate the UIView then it will display properly.
I'm displaying the UIImageView like this (in the UIView):
- (void)showMailSetupPopover {
if (self.popoverMailSetupImageView == nil) {
UIImageView *popoverMailSetupImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"popover-mail-setup-addreminder"]];
popoverMailSetupImageView.alpha = 0.0;
popoverMailSetupImageView.frame = CGRectMake(8, self.frame.origin.y + 65, popoverMailSetupImageView.bounds.size.width, popoverMailSetupImageView.bounds.size.height);
self.popoverMailSetupImageView = popoverMailSetupImageView;
}
[self addSubview:self.popoverMailSetupImageView];
[UIView animateWithDuration:0.5 animations:^{
self.popoverMailSetupImageView.alpha = 1.0;
} completion:^(BOOL finished) {}];
}
This is how I add theUIView to self.view:
RMMessageTypePickerView *messageTypePickerView = [[RMMessageTypePickerView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 260) reminderMessageType:RMReminderMessageTypeText delegate:self];
self.messageTypePickerView = messageTypePickerView;
[self.view addSubview:self.messageTypePickerView];
[UIView animateWithDuration:0.2 animations:^{
self.messageTypePickerView.frame = messageTypePickerViewTargetFrame;
self.addReminderTableView.frame = addReminderTableViewTargetFrame;
} completion:^(BOOL finished) {
if (firstShow) {
[self processSelectedMessageTypeRow:RMReminderMessageTypeText];
}
}];

Found out the issue,
Replaced
popoverMailSetupImageView.frame = CGRectMake(8, self.frame.origin.y + 65, popoverMailSetupImageView.bounds.size.width, popoverMailSetupImageView.bounds.size.height);
with
popoverMailSetupImageView.frame = CGRectMake(8, 65, popoverMailSetupImageView.bounds.size.width, popoverMailSetupImageView.bounds.size.height);
self.frame.origin.y is not needed.

Related

How can I display a fullscreen image with a black background?

I implemented the feature to display a fullscreen image when it is tapped. However this only enlarge the image but does not show it with a black background (the other elements of the view are still in the bakcground). How can I do this?
//Setup touch up inside of the imageview (in viewdidload)
userPictImageView.userInteractionEnabled = YES;
userPictImageView.contentMode = UIViewContentModeScaleAspectFit;
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewFullScreenTouchHandler:)];
tapper.numberOfTapsRequired = 1;
[userPictImageView addGestureRecognizer:tapper];
//present a full screen image (without black background)
-(IBAction)imageViewFullScreenTouchHandler:(id)sender {
//goto new ViewController and set the image
UIImageView *imageView = userPictImageView;
if (!imageIsFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = imageView.frame;
blackView=[[UIView alloc]initWithFrame:self.view.frame];
[blackView setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:blackView];
CGRect frame = self.view.frame;
[imageView setFrame:frame];
[blackView addSubview:imageView]; }
completion:^(BOOL finished){
imageIsFullScreen = TRUE;
}];
return;
}
else{
self.view.backgroundColor = [UIColor clearColor];
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[imageView setFrame:prevFrame];
}completion:^(BOOL finished){
imageIsFullScreen = FALSE;
}];
return;
}
}
You could change to UIViewContentModeScaleToFill, or, probably better, build a UIView with a black background whose frame matches the view frame. Make the image view a subview of that black view.
I'd do it something like this. Create a method that I can call to zoom and unzoom the imageView. To zoom, build a background view and attach the image. To unzoom, do the reverse, and then destroy the background view.
Since the background view will be full screen, attach a gesture recognizer to it so the user can tap to dismiss.
- (void)setUserPictImageViewZoomed:(BOOL)zoom animated:(BOOL)animated {
UIView *blackView = [self.view viewWithTag:128];
BOOL isZoomed = blackView != nil;
// if our current state (isZoomed) matches the desired state (zoomed), then we're done
if (isZoomed == zoom) return;
NSTimeInterval duration = (animated)? 0.3 : 0.0;
if (zoom) {
blackView = [[UIView alloc] initWithFrame:self.view.frame];
blackView.backgroundColor = [UIColor blackColor];
blackView.tag = 128;
blackView.alpha = 0.0;
[self.view addSubview:blackView];
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(unzoom:)];
[blackView addGestureRecognizer:tapGR];
UIImageView *zoomImageView = [[UIImageView alloc] initWithImage:self.userPictImageView.image];
zoomImageView.contentMode = UIViewContentModeScaleAspectFit;
zoomImageView.tag = 129;
zoomImageView.frame = [self.userPictImageView convertRect:self.userPictImageView.frame toView:blackView];
[blackView addSubview:zoomImageView];
[UIView animateWithDuration:duration animations:^{
zoomImageView.frame = blackView.bounds;
blackView.alpha = 1.0;
}];
} else {
UIImageView *zoomImageView = (UIImageView *)[blackView viewWithTag:129];
[UIView animateWithDuration:duration animations:^{
zoomImageView.frame = self.userPictImageView.frame;
blackView.alpha = 0.0;
} completion:^(BOOL finished) {
[blackView removeFromSuperview];
}];
}
}
- (void)unzoom:(UIGestureRecognizer *)gr {
[self setUserPictImageViewZoomed:NO animated:YES];
}
I tested this quickly in a simulator and it looked pretty slick.

Animating status bar iOS 7

Im trying (struggling) to implement a snapchat like error message display for my app (snapchat error messages slide down over the status bar somehow) in iOS7. I cannot for the life of me get my animation to work right. Here is my method that does the animation
- (void)animateHeaderViewWithText:(NSString *)text {
//add header views
[self.headerView addSubview:self.headerLabel];
[self.navigationController.view addSubview:self.headerView];
//Hide the Status Bar
statusBarHidden = TRUE;
[self setNeedsStatusBarAppearanceUpdate];
self.headerLabel.text = text;
[UIView animateWithDuration:.5 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.headerLabel.frame = CGRectMake(0, 0, 320, 20);
self.headerView.frame = CGRectMake(0, 0, 320, 20);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.5 delay:5.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
//UnHide the Status Bar
statusBarHidden = FALSE;
[self setNeedsStatusBarAppearanceUpdate];
self.headerLabel.frame = CGRectMake(0, -20, 320, 20);
self.headerView.frame = CGRectMake(0, -20, 320, 20);
} completion:^(BOOL finished) {
[self.headerView removeFromSuperview];
[self.headerLabel removeFromSuperview];
}];
}];
}
Only the second half of the animation really works right, the message slides back up fine and the status bar appears underneath it. However, the first half of the animation, when the view slides down, the status bar disappears causing my navigation bar to move up, screwing up my animation. How can I get my navigation bar to stay where it is initially placed, even when the status bar is gone
This code worked in portrait, but would need to be modified to work properly in both orientations. It uses a separate UIWindow as the overlay, so there's no need to hide or unhide the status bar.
#interface ViewController ()
#property (strong,nonatomic) UIWindow *dropdown;
#property (strong,nonatomic) UILabel *label;
#property (strong,nonatomic) UIWindow *win;
#end
#implementation ViewController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.dropdown = [[UIWindow alloc] initWithFrame:CGRectMake(0, -20, 320, 20)];
self.dropdown.backgroundColor = [UIColor redColor];
self.label = [[UILabel alloc] initWithFrame:self.dropdown.bounds];
self.label.textAlignment = NSTextAlignmentCenter;
self.label.font = [UIFont systemFontOfSize:12];
self.label.backgroundColor = [UIColor clearColor];
[self.dropdown addSubview:self.label];
self.dropdown.windowLevel = UIWindowLevelStatusBar;
[self.dropdown makeKeyAndVisible];
[self.dropdown resignKeyWindow];
}
- (IBAction)dropDown:(UIButton *)sender {
[self animateHeaderViewWithText:#"This is my test string"];
}
-(void)animateHeaderViewWithText:(NSString *) text {
self.label.text = text;
CGRect frame = self.dropdown.frame;
frame.origin.y = 0;
[UIView animateWithDuration:.6 delay:0 options:0 animations:^{
self.dropdown.frame = frame;
}completion:^(BOOL finished) {
;
}];
}

How to correctly enlarge an image from within a table view

I'm using the following code to zoom/enlarge an image from within a table view. I would like it to enlarge out to full screen. the current problem is that when it enlarges it enlarges only within the table cell (and as a result is partially hidden beneath the next table cell) instead of the full view.
-(void)zoomPhotoMethod :(id) sender
{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(#"Tag = %d", gesture.view.tag);
userSubmittedImageView = (UIImageView *)gesture.view;
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = userSubmittedImageView.frame;
UIView *popupImageViewForTableCell = [[UIView alloc] initWithFrame: CGRectMake ( 0, 0, 320, 500)];
[userSubmittedImageView setFrame:[popupImageViewForTableCell bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[userSubmittedImageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;;
}];
return;
}
}
updated code:
-(void)zoomPhotoMethod :(id) sender
{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(#"Tag = %d", gesture.view.tag);
userSubmittedImageView = (UIImageView *)gesture.view;
if (!isFullScreen) {
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
//save previous frame
prevFrame = userSubmittedImageView.frame;
newView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
[self.view addSubview:newView];
UIView *popupImageViewForTableCell = [[UIView alloc] initWithFrame: CGRectMake ( 0, 0, 320, 500)];
[userSubmittedImageView setFrame:[popupImageViewForTableCell bounds]];
[newView addSubview:userSubmittedImageView];
[userSubmittedImageView setFrame:[newView bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
[userSubmittedImageView setFrame:prevFrame];
[newView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;;
}];
return;
}
}
What's happening is that you are still a subview of the tableview cell, so it's not going to be able to go outside of those bounds without being clipped.
To do what you want to do, you're going to have to:
Create a new UIImageView outside of your table view (add it as a subview outside of the tableview).
Set the image in the image view to the same image that you have in the tableview cell.
Start it at the same size and position as your tableview cell image.
Animate it up to where you want it.
When it's time to remove it, move it back down to the original tableview cell image.
Discard the imageview.
One way would be to use a copy of the image and place it outside the cell just above your original and animate this second image to full screen.
Another way would be to increase the tableView rowHeight and reload the section.

UIView animation not working properly

I'm having some problems with UIView subview animations. What I'm trying to do is that when you press the main view, a subview will slide down from the top and on the next tap it will slide up and be removed. But in the current state, it just does the first tap commands and on the second tap, it displays a nslog, but the removal of the view and the animation doesn't work.
Here is the code in the event handling function:
- (void)tapGestureHandler: (UITapGestureRecognizer *)recognizer
{
NSLog(#"tap");
CGRect frame = CGRectMake(0.0f, -41.0f, self.view.frame.size.width, 41.0f);
UIView *topBar = [[UIView alloc] initWithFrame:frame];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"topbar.png"]];
topBar.backgroundColor = background;
if (topBarState == 0) {
[self.view addSubview:topBar];
[UIView animateWithDuration:0.5 animations:^{topBar.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 41.0f);}];
topBarState = 1;
} else if (topBarState == 1){
[UIView animateWithDuration:0.5 animations:^{topBar.frame = CGRectMake(0.0f, -41.0f, self.view.frame.size.width, 41.0f);} completion:^(BOOL finished){[topBar removeFromSuperview];}];
NSLog(#"removed");
topBarState = 0;
}
}
How do i make it so that the subview animate and is removed properly?
Best Regards
FreeSirenety
you are always set the topBar frame with y = -41, so for topBarState = 1, animation works for y=-41 to y=-41 and seems to be as not working
CGRect frame = CGRectMake(0.0f, -41.0f, self.view.frame.size.width, 41.0f);
UIView *topBar = [[UIView alloc] initWithFrame:frame];
every time you are creating the view topBar.
Declare topBar in .h and alloc init in viewDidLoad.
- (void)viewDidLoad {
CGRect frame = CGRectMake(0.0f, -41.0f, self.view.frame.size.width, 41.0f);
topBar = [[UIView alloc] initWithFrame:frame];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"topbar.png"]];
topBar.backgroundColor = background;
[self.view addSubview:topBar];
topBarState = 0;
}
- (void)tapGestureHandler: (UITapGestureRecognizer *)recognizer
{
if (topBarState == 0) {
[UIView animateWithDuration:0.5 animations:^{topBar.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 41.0f);}];
topBarState = 1;
} else if (topBarState == 1){
[UIView animateWithDuration:0.5 animations:^{topBar.frame = CGRectMake(0.0f, -41.0f, self.view.frame.size.width, 41.0f);} completion:^(BOOL finished){[topBar removeFromSuperview];}];
topBarState = 0;
}
}

UIButton label not respecting text set by completion handler of previous animation when selected

On the touchUpInside call of _menuButton, I perform an animation to show the menu with a completion block to change the label of the menu from "open" to "close". That animation works fine, but when you press down on _menuButton it instantly changes from "close" to "menu" even if the user cancels the tap or slides off of the button. The initial text of the button label is "menu".
Not sure if it makes a difference, but my property for _menuButton is:
#property (weak, nonatomic) IBOutlet UIButton *menuButton;
Animation to load menu:
[UIView animateWithDuration:0.50
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
_menuButton.center = CGPointMake(_menuButton.center.x + 120, _menuButton.center.y);
_quitButton.center = CGPointMake(_quitButton.center.x + 215, _quitButton.center.y);
_rulesButton.center = CGPointMake(_rulesButton.center.x + 215, _rulesButton.center.y);
_preferencesButton.center = CGPointMake(_preferencesButton.center.x + 215, _preferencesButton.center.y);
_quitButton.alpha = 1.0f;
_rulesButton.alpha = 1.0f;
_preferencesButton.alpha = 1.0f;
_menuButton.alpha = 1.0f;
} completion:^(BOOL finished) {
_menuButton.titleLabel.text = #"close";
}];
Animation to unload menu:
[UIView animateWithDuration:0.50
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
_menuButton.center = CGPointMake(_menuButton.center.x - 120, _menuButton.center.y);
_quitButton.center = CGPointMake(_quitButton.center.x - 215, _quitButton.center.y);
_rulesButton.center = CGPointMake(_rulesButton.center.x - 215, _rulesButton.center.y);
_preferencesButton.center = CGPointMake(_preferencesButton.center.x - 215, _preferencesButton.center.y);
_quitButton.alpha = 0.0f;
_rulesButton.alpha = 0.0f;
_preferencesButton.alpha = 0.0f;
_menuButton.alpha = 0.6f;
} completion:^(BOOL finished) {
_menuButton.titleLabel.text = #"menu";
}];
change _menuButton.titleLabel.text = #"close"; to
[_menuButton setTitle:#"close" forState:normal];
see
UIButton Class Reference.
UIButton provides methods for interrogating and setting the title. The one you're looking for is:
- (void)setTitle:(NSString *)title forState:(UIControlState)state

Resources