I'm learning how to implement custom view transition. I want to create a slide menu something like spotify side menu. I'm using UIViewControllerAnimatedTransitioning. The animation seems to be working but after dismissing transition, the screen become blank.
This is the code for presenting transition
#import "Transition.h"
#implementation Transition
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 1;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
UIViewController *to=[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *from=[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView=[transitionContext containerView];
to.view.alpha=0.0;
[containerView addSubview:to.view];
[containerView addSubview:from.view];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
from.view.frame = CGRectMake(200, 0, from.view.frame.size.width, from.view.frame.size.height);
from.view.alpha=1.0;
to.view.alpha=1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
#end
This is the code for dismissal transition
#import "DismissTransition.h"
#implementation DismissTransition
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 1;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContex{
UIViewController *from=[transitionContex viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *to=[transitionContex viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView=[transitionContex containerView];
[UIView animateWithDuration:[self transitionDuration:transitionContex] animations:^{
to.view.frame = CGRectMake(0, 0, from.view.frame.size.width, from.view.frame.size.height);
to.view.alpha=1.0;
from.view.alpha=0.0;
} completion:^(BOOL finished) {
[transitionContex completeTransition:YES];
}];
}
#end
This is where my custom transition is called
#import "ViewController.h"
#import "Transition.h"
#import "DismissTransition.h"
#import "MenuViewController.h"
#interface ViewController ()<UIViewControllerTransitioningDelegate>
#end
#implementation ViewController
- (IBAction)buttonTap:(id)sender {
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MenuViewController* viewController = [mystoryboard instantiateViewControllerWithIdentifier:#"MenuVC"];
viewController.modalPresentationStyle=UIModalPresentationCustom;
viewController.transitioningDelegate=self;
[self presentViewController:viewController animated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source{
return [[Transition alloc]init];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
return [[DismissTransition alloc]init];
}
#end
And this is how I dismiss MenuViewController
#import "MenuViewController.h"
#interface MenuViewController ()
#end
#implementation MenuViewController
- (IBAction)doneButtonTap:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You should add to.view to containerView in DismissTransition
Related
Keeping popover in open state. Then, when I try to switch to 2/3 screen mode and change the position of center BarButtonItem with fixed space BarButtonItem in viewWillTrainsition, my popover tool-tip moves to the previous location of barButtonItem.
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
if (size.width>size.height) {
_fixedSpace.width = 280;
} else {
_fixedSpace.width = 80;
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
}];}
From iOS11, bar button item is using constraint instead of frames. So try giving a constraint to each bar button item. It might doesn't reflect visually but it plays a major role in producing this kind of issue.
Try using below code to set the constraint:
if #available(iOS 11.0, *)
{
_fixedSpace.widthAnchor.constraint(equalToConstant: 280.0).isActive = true
}
Hope this helps!
I replicated same scenario and I found a fix for this as below:
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
if (size.width > size.height) {
fixedSpace.width = 280;
} else {
fixedSpace.width = 80;
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
CGRect rect = [self.view convertRect:barBtn.frame fromView:barBtn];
popover.sourceRect = rect;
}];
Try to reset the sourceRect property in the completion block.
Hope this is helpful!
As far as I understood your question I want to propose a simple solution for this :
I have took a Viewcontroller and PopoverView in storyboard. Viewcontroller will work as main view controller where as PopoverView will work to display as popover.
(Caution : Don’t Forget to set Explicit Content Size for PopoverView in StoryBoard) for more reference you can see attached screen shot of my storyboard.
Here is sample source code of Viewcontroller in which you will find Popoverview position will change as per the right button frame change.
This code is developed using Objective C
ViewController.h
//
// ViewController.h
// SOPopoverControllerDemo
//
// Created by Test User on 08/01/18.
// Copyright © 2018 Test User All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
ViewController.m
//
// ViewController.m
// SOPopoverControllerDemo
//
// Created by Test User on 08/01/18.
// Copyright © 2018 Test User All rights reserved.
//
#import "ViewController.h"
#interface ViewController () <UIPopoverPresentationControllerDelegate>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *leftToolBarBtn;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *rightToolBarBtn;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *flexibleBtn;
#property (weak, nonatomic) IBOutlet UIToolbar *bottomToolBar;
#property (weak,nonatomic) UIPopoverPresentationController *popOverController;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if (self.view.frame.size.width > self.view.frame.size.height) {
self.rightToolBarBtn.width = 200;
self.leftToolBarBtn.width = 200;
} else {
self.rightToolBarBtn.width = 150;
self.leftToolBarBtn.width = 150;
}
}
- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
if (size.width > size.height) {
_rightToolBarBtn.width = 200;
[self dismissViewControllerAnimated:true completion:nil];
[self rightToolBarBtnTapped:_rightToolBarBtn];
} else {
_rightToolBarBtn.width = 150;
[self dismissViewControllerAnimated:true completion:nil];
[self rightToolBarBtnTapped:_rightToolBarBtn];
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
}];
}
- (IBAction)rightToolBarBtnTapped:(id)sender {
//Grab the controller for popover
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"PopoverView"];
if (self.view.frame.size.width > self.view.frame.size.height ) {
controller.preferredContentSize = CGSizeMake(200, 100);
} else {
controller.preferredContentSize = CGSizeMake(150, 100);
}
controller.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:controller animated:YES completion:nil];
// configure the Popover presentation controller
_popOverController = [controller popoverPresentationController];
_popOverController.delegate = self;
_popOverController.permittedArrowDirections = UIPopoverArrowDirectionUp;
_popOverController.barButtonItem = self.rightToolBarBtn;
}
//--------------------------------------------------
#pragma mark -> UIPopOverController Delegate
//--------------------------------------------------
- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
return YES;
}
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"Popover Did Dismissed");
}
#end
PopoverView.h
//
// PopoverView.h
// SOPopoverControllerDemo
//
// Created by Test User on 08/01/18.
// Copyright © 2018 Test User All rights reserved.
//
#import <UIKit/UIKit.h>
#interface PopoverView : UIViewController
#end
PopoverView.m
//
// PopoverView.m
// SOPopoverControllerDemo
//
// Created by Test User on 08/01/18.
// Copyright © 2018 Test User All rights reserved.
//
#import "PopoverView.h"
#interface PopoverView ()
#end
#implementation PopoverView
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I am beginner in iOS. In my ParentViewController I am adding one ChildViewController. In that controller I have added one Next button. When I click that button I am pushing First ChildViewController to Second ChildViewController. That's fine.
But here I have added another Button in Second ChildViewController. When i click that button I want to push back from Second ChildViewController to First ChildViewController. But with my code that's not working. Please help me someone
My code:
ParentViewController:
#import "ParentViewController.h"
#interface ParentViewController ()
#end
#implementation ParentViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
ChildViewController1 *ViewController1 = [self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController1"];
ViewController1.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
ViewController1.view.backgroundColor = [UIColor cyanColor];
[ViewController1 willMoveToParentViewController:self];
[self.view ViewController1.view];
[self ViewController1];
}
#end
ChildViewController1:
#import "ChildViewController1.h"
#interface ChildViewController1 ()
{
}
#end
#implementation ChildViewController1
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)next:(id)sender{
ChildViewController2 *middleVC =[self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController2"];
middleVC.view.hidden=FALSE;
[middleVC.view setFrame:CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self addChildViewController:middleVC];
[self.view addSubview:middleVC.view];
[middleVC didMoveToParentViewController:self];
[UIView animateWithDuration:0.5 animations:^{
[middleVC.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}];
}
ChildViewController2:
#import "ChildViewController2.h"
#interface ChildViewController2 ()
{
}
#end
#implementation ChildViewController2
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)back:(id)sender {
ChildViewController2 *middleVC =[self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController2"];
middleVC.view.hidden=FALSE;
[middleVC.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self addChildViewController:middleVC];
[self.view addSubview:middleVC.view];
[middleVC didMoveToParentViewController:self];
[UIView animateWithDuration:0.5 animations:^{
[middleVC.view setFrame:CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height)];
}];
}
Here when I click this back button it's not pushing it back.
Inside the ChildViewController2 back button action you have:
ChildViewController2 *middleVC =[self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController2"];
Don't you mean:
ChildViewController1 *middleVC =[self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController1"];
// // PopupViewController.h // TheStore
// // Created by Daniel Habshush on 11.04.15. // Copyright (c) 2015
H Company. All rights reserved. //
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "AppDelegate.h"
#interface PopupViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIView *popUpView;
- (void)showInView:(UIView *)aView animated:(BOOL)animated;
#end
// // PopupViewController.m // TheStore // // Created by Daniel
Habshush on 11.04.15. // Copyright (c) 2015 H Company. All rights
reserved. //
#import "PopupViewController.h"
#interface PopupViewController ()
#end
#implementation PopupViewController
- (void)viewDidLoad
{
self.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:.6];
self.popUpView.layer.cornerRadius = 5;
self.popUpView.layer.shadowOpacity = 0.8;
self.popUpView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
[super viewDidLoad];
}
- (void)showAnimate
{
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.view.alpha = 0;
[UIView animateWithDuration:.25 animations:^{
self.view.alpha = 1;
self.view.transform = CGAffineTransformMakeScale(1, 1);
}
- (void)removeAnimate
{
[UIView animateWithDuration:.25 animations:^{
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3);
self.view.alpha = 0.0;
} completion:^(BOOL finished) {
if (finished) {
[self.view removeFromSuperview];
}
}];
}
- (IBAction)closePopup:(id)sender {
[self removeAnimate];
}
- (void)showInView:(UIView *)aView animated:(BOOL)animated
{
[aView addSubview:self.view];
if (animated) {
[self showAnimate];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
}
#end
So, my question is:
I want to add a PopupView Controller to main.storyboard but can't somehow solve the last error.
You're missing the closing curly brace in your showAnimate method, which gives you an error in the following method.
i made an UIview as a subview to be as a top slid menu bar when touch button it will slide down and it is work fine but the problem is when it down i can not access any tools or buttons in it
in the .h file
#import <UIKit/UIKit.h>
#interface MainGameVC : UIViewController
{
//IBOutlet UIView *TopMenuViewer;
int Menu;
}
#property (nonatomic, retain) IBOutlet UIView *TopMenuViewer;
#property (strong, nonatomic) IBOutlet UITextField *TestText;
-(IBAction)OpenMenu:(id)sender;
#end
in the .m file
#import "MainGameVC.h"
#interface MainGameVC ()
#property (strong, nonatomic) IBOutlet UITextField *TextBox;
#end
#implementation MainGameVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(IBAction)OpenMenu:(id)sender{
if (Menu == 0) {
Menu = 1;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
self.TopMenuViewer.Frame = CGRectMake(0, -100, 0, 0);
[UIView commitAnimations];
[self.view bringSubviewToFront:self.TopMenuViewer];
[self.TopMenuViewer accessibilityElementDidBecomeFocused];
}else{
Menu = 0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
self.TopMenuViewer.Frame = CGRectMake(0, 0, 0, 0);
[UIView commitAnimations];
[self.view bringSubviewToFront:self.TopMenuViewer];
[self.TopMenuViewer accessibilityElementDidBecomeFocused];
[self.TopMenuViewer accessibilityElements];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
Menu = 0;
self.TopMenuViewer.Frame = CGRectMake(0, 0, 0, 0);
[
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Not sure that AllowUserInteraction will solve your issue. This is approach to set options for the animation:
-(IBAction)OpenMenu:(id)sender{
if (Menu == 0) {
Menu = 1;
[UIView animateWithDuration:.5
delay:0.0
options:(UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionCurveEaseInOut)
animations:^
{
self.TopMenuViewer.Frame = CGRectMake(0, -100, 0, 0);
}
completion:^(BOOL finished){
[self.TopMenuViewer accessibilityElementDidBecomeFocused];
}];
Consider attaching the project to the question for us to have a look.
should use UIScrollView instead of UIView
I want to animation change button title. example, the title of button is "one", after I click that button, fade out "one" and then fade in "NewTitle".
Rather than messing around with duplicate views, simple fade transitions can be made with the CATransition class.
// CATransition defaults to fade
CATransition *fade = [CATransition animation];
// fade.duration = ...
[button.layer addAnimation:fade];
[button setTitle:#"New title" forControlState:UIControlStateNormal];
The button will fade to its new state. This works for labels, entire view hierarchies, whatever.
So creating two buttons was not a good Idea so I have created a simple project to test code for your question and here is what I come up with
viewcontroller.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UIButton *myButton;
}
#property(nonatomic,strong) IBOutlet UIButton *myButton;
-(IBAction)animateFadeOutButtonTitle:(id)sender;
-(void)animateFadeInButtonTitle;
#end
viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myButton=_myButton;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_myButton setTitle:#"One" forState:UIControlStateNormal];
}
-(IBAction)animateFadeOutButtonTitle:(id)sender
{
[UIView animateWithDuration:0.25 animations:^{_myButton.titleLabel.alpha = 0.0;}];
[self performSelector:#selector(animateFadeInButtonTitle) withObject:self afterDelay:1.0];
}
-(void)animateFadeInButtonTitle;
{
[_myButton setTitle:#"New Title" forState:UIControlStateNormal];
[UIView animateWithDuration:2.0
delay:0.0
options: UIViewAnimationCurveEaseInOut
animations:^{_myButton.titleLabel.alpha = 1.0;}
completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end