how to set an uiview fullscreen dynamically? - ios

I have an app which has two subviews.I wanna double tap the video view(the top one) to make it fullscreen to display video.(By fullscreen, I mean it should be in landscape mode) So how should I do in the method -(void)handleTapGesture::(UITapGestureRecognizer*)recognizer?
I guess, first of all, I should hide status bar and navigation bar; then rotate the video view to make it landscape left/right programmatically.
BTW, for some reason, I have to make my app only support portrait mode.Forgive my terrible English, if you don't understand my question clearly, plz leave a comment, thanks.
Update:
I've hided status bar and navigation bar both, but when I make the video view fullscreen, it seems navigation bar and status bar are still there and my video view cannot move up to the top of the screen!
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[self.navigationController.navigationBar setHidden:YES];
[UIView beginAnimations : #"video full screen" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationBeginsFromCurrentState:YES];
self.videoView.frame = self.view.bounds;
moviewGLView.frame = CGRectMake(0, 0, self.videoView.frame.size.width, self.videoView.frame.size.width*3/4);
moviewGLView.center = self.videoView.center;
videoDefault.center = self.videoView.center;
[UIView commitAnimations];

add this code in your ViewDidLoad() method
UITapGestureRecognizer *tapOnTopView = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(makeTopViewFullScreen)];
tapOnTopView.numberOfTapsRequired = 1;
[topView addGestureRecognizer:tapOnTopView];
add the following function
-(void)makeTopViewFullScreen
{
[UIView animateWithDuration:0.3
animation:^
{
topViewHeightConstraint = self.view.frame.size.height;
bottomViewHeightConstraint = 0;
[self layoutIfNeeded];
}
completion:^
{
//your code to rotate the topView
}
}
note that the topViewHeightConstraint and bottomViewHeightConstraint should be outlets connected in IB.
Hope that helps, let me know if you need more help.

Related

Move UIToolBar above keyboard on screen with UIScrollview

I have a screen within an iPhone app that consist of a UITextView. This text view is contained within a UIScrollView. The purpose of the screen is for the user to type in text, and to optionally attach an image to what he is writing. Therefore, the screen also has a UIToolbar with a camera button at the bottom of the screen. The structure of the screen is as follows:
-View
--UIScrollView
---UITextView
--UIToolbar
---UIButton
When the user navigates to this screen, the viewDidAppear method assigns first responder to the uitextview element, so the keyboard shows up, which hides the toolbar and the camera button.
I would like the entire toolbar to re-draw itself right above the keyboard, and to position itself again at the bottom of the screen when the keyboard hides.
I have found related posts on SO (like this one). However, such methods introduce undesired behaviours. For example, implementing the solution in the article above, the toolbar does move with the keyboard, but the UIScrollView gets its frame.origin.y coordinate shifted way above the top of the screen, so it's impossible for the user to see what he is typing.
I have also tried to reset the frame of the toolbar, by adding it as an IBOutlet and using cgrectmake to reposition it. However, after several tries, the toolbar remains stuck at the bottom of the screen and hidden by the keyboard:
- (void) liftMainViewWhenKeybordAppears:(NSNotification*)aNotification{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:<#(UIViewAnimationCurve)#>]
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.keyboardToolbar.frame.origin.y - 280;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
I have tried several iterations similar to the code above and they all fail at repositioning the toolbar.
So in short, what is the right way to float a toolbar right on top of a keyboard in a screen whose space is completely utilised by a uitextview element?
Thanks to RoryMcKinnel for the pointer. As the article referenced is in Swift, I thought I might paste the solution that worked for be on ObjC
- (void)keyboardWillShowNotification:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;
double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect convertedKeyboardFrame = [self.view convertRect:keyboardEndFrame fromView:self.view.window];
UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
_toolBarBottomGuide.constant = CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedKeyboardFrame);
[UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
Bear in mind, this code did make the toolbar move as required, but the toolbar was not visible at all. It turned out that it was being hidden behind the UIScrollView. This was easily fixed by shifting the order between the scroll view and the toolbar element in the IB hierarchy.
The method above works for the keyboardWillShow event. You'll need to add the corresponding one for when the keyboard hides, like this:
- (void)keyboardWillHideNotification:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;
double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationOptions rawAnimationCurve = (UIViewAnimationOptions)[userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
_toolBarBottomGuide.constant = 0.0f;
[UIView animateWithDuration:animationDuration delay:0.0 options:rawAnimationCurve animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}

Best approach for Nested UINavigationController

I have two viewControllers for iPad just like facebook sidepanel. There is LeftViewController which toggles when I click a button on center viewController. It slides on the top of CenterViewController. But it covers only 50% of centerViewController.
I should be able to add new views to left viewController and can push.
What is the best approach to achieve this.
Please check this link
Sliding Drawers
[SideMenus]
This contains different drawers and few in swift too. may be this link would be helpful to you.
you can add slide-in side bar in view.see below my code.
assign the property in .h file
UIView*menuDrawer;
#property(readonly,nonatomic)UISwipeGestureRecognizer*recognizer_open,*recognizer_close;
#property(readonly,nonatomic) int menuDrawerX,menuDrawerWidth;
//customize slide menu
Add this code in viewdidload
int statusBarHeight=[UIApplication sharedApplication].statusBarFrame.size.height-20;
menuDrawerWidth=self.view.frame.size.width*0.65;//you can adjust width
menuDrawerX=self.view.frame.origin.x-menuDrawerWidth;
menuDrawer=[[UIView alloc]initWithFrame:CGRectMake(menuDrawerX, self.view.frame.origin.y+statusBarHeight, menuDrawerWidth,self.view.frame.size.height-statusBarHeight)];
menuDrawer.backgroundColor=[UIColor
whiteColor];
recognizer_close=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(handleSwipes:)];
recognizer_open=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(handleSwipes:)];
recognizer_close.direction=UISwipeGestureRecognizerDirectionLeft;
recognizer_open.direction=UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:recognizer_close];
[self.view addGestureRecognizer:recognizer_open];
[self.view addSubview:menuDrawer];
add this method
-(void)handleSwipes:(UISwipeGestureRecognizer*)sender
{
[self drawerAnimation];
}
call this method,if you are assigning a button also can set selector of a button
-(void)drawerAnimation
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:-5];
CGFloat new_x = 0;
if (menuDrawer.frame.origin.x < self.view.frame.origin.x) {
new_x=menuDrawer.frame.origin.x + menuDrawerWidth;
}
else
{
new_x=menuDrawer.frame.origin.x - menuDrawerWidth;
}
menuDrawer.frame=CGRectMake(new_x, menuDrawer.frame.origin.y, menuDrawer.frame.size.width, menuDrawer.frame.size.height);
[UIView commitAnimations];
}
it will work fine,you can add UITableView or other controls in these slide-in side bar menu.
you can adjust height and width via statusBarHeight and menuDrawerWidth.

iOS Simultaneous animations without completion block

I have a video player that has a standard toolbar. The toolbar is dismissed by a swipe down gesture. I also have a view (a panel really) that can appear directly above the toolbar and is also dismissed by a swipe down gesture. When both the panel and the toolbar are open, one swipe down gesture should dismiss the panel, a second will dismiss the toolbar. Problem is that when the swipe gestures occur quickly back-to-back (before the panel animation completes) then the toolbar animation jitters.
- (void)handleSwipe:(UISwipeGestureRecognizer *)gestureRecognizer
{
UISwipeGestureRecognizerDirection direction = [gestureRecognizer direction];
if (direction == UISwipeGestureRecognizerDirectionDown) {
if (![toolbar isHidden]) {
// Only dismiss the bottom panel if it is open
if (_selectedSegmentIndex != UISegmentedControlNoSegment) {
_selectedSegmentIndex = UISegmentedControlNoSegment;
[bottomPanelView dismissPanel];
} else {
CGRect tempRect = CGRectMake(0, self.view.frame.size.height, toolbar.frame.size.width, toolbar.frame.size.height);
[UIView animateWithDuration:0.25f
animations:^{
// Move the toolbar off the screen.
toolbar.frame = tempRect;
}
completion:^(BOOL finished) {
[toolbar setHidden:YES];
}];
}
}
}
}
[bottomPanelView dismissPanel] is in a separate class and is not aware of the class that calls it. It has the follow animation...
[UIView animateWithDuration:self.panelAnimationDuration
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// slideOutLocation is off the screen
self.view.frame = slideOutLocation;
}
completion:^(BOOL finished) {
[self.view removeFromSuperview];
[self removeFromParentViewController];
self.panelActive = NO;
}];
So basically, the dismissPanel animation is still running when the animation to dismiss the toolbar begins. When performing a double swipe in slow motion in the simulator, the first animation looks fine, but the toolbar animation is jittery.
I know how to nest animations in the completion block, but that cannot be done here since dismissing both the panel and the toolbar is not always what is wanted. Also, the dismissPanel code is handled elsewhere and is not in control of the toolbar.
Is there a way to allow multiple animation blocks to run simultaneously without putting the completion block? Let me know if any clarification is needed! Thanks!
I wonder if the problem might have to do with auto layout (setting frames while auto layout is on causes problems). I tried a simple test of animating a view and a tool bar off the bottom of the screen by animating their constraint constants, and the animation looked fine. I made IBOutlets to their respective bottom constraints (called viewBottomCon and toolBarBottomCon).
- (void)viewDidLoad {
[super viewDidLoad];
self.isFirstSwipe = YES;
}
-(IBAction)downSwipe:(UISwipeGestureRecognizer *)sender {
if (self.isFirstSwipe) {
self.viewBottomCon.constant = -52;
self.isFirstSwipe = NO;
[UIView animateWithDuration:5 animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}else if (!self.isFirstSwipe) {
self.toolBarBottomCon.constant = -44;
[UIView animateWithDuration:3 animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
}
This is a simpler setup than yours, but I think it should work in your case too.

Weird positioning issue when tabBar is present

We have a custom view with a UIPickerView plus toolbar (216 + 44). At init time (viewDidLoad) this custom view is pushed below the screen using the following piece of code.
CGPoint newOrigin;
newOrigin.x = pickerViewOutlet.frame.size.width/2;
newOrigin.y = self.view.frame.size.height + ((pickerViewOutlet.frame.size.height)/2);
NSLog(#"%f,%f",self.view.frame.size.height,(pickerViewOutlet.frame.size.height)/2);
pickerViewOutlet.center = CGPointMake(newOrigin.x, newOrigin.y);
When a button is clicked this view is pulled up using the following piece of code.
[self.view bringSubviewToFront:pickerViewOutlet];
NSLog(#"tabbar %f",self.tabBarController.tabBar.frame.size.height);
CGPoint showOrigin;
showOrigin.x = pickerViewOutlet.frame.size.width/2;
showOrigin.y = pickerViewOutlet.center.y - pickerViewOutlet.frame.size.height;
//self.tabBarController.tabBar.frame.size.height ;
NSLog(#"showpicker %f,%f",pickerViewOutlet.center.y,pickerViewOutlet.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
pickerViewOutlet.center=CGPointMake(showOrigin.x, showOrigin.y);
[UIView commitAnimations];
[pickerCtrlOutlet reloadAllComponents];
This works fine. However this does not work (part of the view is below the tab bar) in the presence of a bottom tab bar controller on the page even though the code is modified as
showOrigin.y = pickerViewOutlet.center.y - pickerViewOutlet.frame.size.height - self.tabBarController.tabBar.frame.size.height ;
However if the above code is modified to
showOrigin.y = pickerViewOutlet.center.y - pickerViewOutlet.frame.size.height - self.tabBarController.tabBar.frame.size.height - 90;
it works perfectly where the view is right above the tab bar.
As far as I know, in viewDidLoad the self.view is not yet added to the superview and thus the frame is not set to the correct sizes.
For example, you can design a UIView in InterfaceBuilder and it will have 320x460. When you add it to the superview it will actually become smaller because of the bottom tab bar. The auto-resizing mechanism helps in this matter.
So, I think you are positioning the picker view using the wrong values in viewDidLoad and then when you use a new position relative to its old one, it will still be wrong.
Here is how I would write this:
[self.view bringSubviewToFront:pickerViewOutlet];
NSLog(#"tabbar %f",self.tabBarController.tabBar.frame.size.height);
CGPoint showOrigin;
showOrigin.x = pickerViewOutlet.frame.size.width/2;
//Notice this line -----------
showOrigin.y = self.view.frame.size.height - pickerViewOutlet.frame.size.height / 2;
//self.tabBarController.tabBar.frame.size.height ;
NSLog(#"showpicker %f,%f",pickerViewOutlet.center.y,pickerViewOutlet.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
pickerViewOutlet.center=CGPointMake(showOrigin.x, showOrigin.y);
[UIView commitAnimations];
[pickerCtrlOutlet reloadAllComponents];
Notice showOrigin.y = self.view.frame.size.height - ...
And (for extra points :) you can set the autoresizing masks for the picker view to Flexible Top (or, lock the bottom coordinate). If you do this, even if you position the picker view in viewDidLoad and then the self.view resizes, the pickerview will also change it's position.

How do I perform these animated view transitions?

I am brand new to Core Animation, and I need to know how to do 2 animations:
I need to switch XIBs by fading through black (fully releasing the the first view controller)
I need to mimic the UINavigationController's pushViewController animation (switching XIBs and releasing the first view controller)
How can you achieve these animated view transitions?
I've done both of these animations, but maybe not in the exact way you are looking for.
Fade View to black, I took this the other way an instead added a new
subview that covered the entire window that was Black and animated
the Alpha from 0.0 to 1.0. Made for a nice effect.
[UIView animateWithDuration:0.5
animations:^{ _easterEgg.alpha = 1.0; }
completion:^(BOOL finished) { [self animateIndex:0]; }];
Slide in a view like UINavigationController. I didn't do this exactly like UINavigationController since it does multiple animations, but I did have a new view slide the previous view off screen. This code sets the frame of the new view off screen to the right of the current view, builds a frame location that is off the screen to the left, and grabs the current visible frame. Finally it just animates the new view from off screen right into the visible frame, and the old view from the visible frame to off left. Then removes the old view.
CGRect offRight = CGRectMake(_contentView.frame.size.width,
0,
_contentView.frame.size.width,
_contentView.frame.size.height);
CGRect offLeft = CGRectMake(-_contentView.frame.size.width,
0,
_contentView.frame.size.width,
_contentView.frame.size.height);
CGRect visibleFrame = CGRectMake(0, 0, _contentView.frame.size.width, _contentView.frame.size.height);
[view setFrame:offRight];
UIView *currentView = [[_contentView subviews] lastObject];
[_contentView addSubview:view];
[UIView animateWithDuration:0.5
animations:^{
[currentView setFrame:offLeft];
[view setFrame:visibleFrame];
}
completion:^(BOOL finished) {
[currentView removeFromSuperview];
}];

Resources