I used the code below to present vViewController1
#property (retain,nonatomic) ViewController1 *vViewController1;
...
push vViewController1 from rootViewController
[self.navigationController pushViewController:vViewController1 animated:NO];
Viewcontroller1's viewWillAppear
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect screen = [[UIScreen mainScreen] bounds];
if (self.navigationController) {
CGRect frame = self.navigationController.view.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
self.navigationController.view.frame = frame;
} else {
if ([self respondsToSelector: #selector(containerView)]) {
UIView *containerView = (UIView *)[self performSelector: #selector(containerView)];
CGRect frame = containerView.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
containerView.frame = frame;
} else {
CGRect frame = self.view.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
self.view.frame = frame;
}
}
}
}
but it displays as below and does not move down 20px(height of the statusbar)
Your comment welcome
Assuming you are NOT using Autolayout (seeing as you are playing with frame sizes) then in Storyboard select the ViewController and then goto the Size Inspector (little ruler) and then adjust the Y delta for the view (change to 20 or -20 depending on what mode you are "View As").
This may help here although I am not sure about the 18 value in Y I always thought it was 20!
Related
I know this question has been asked earlier but i am not getting any specific answer to my problem. I am using page control and scrollView to add view controllers and then showing all the pages using swipe. I need to redirect to a particular page on button click. I tried scrollView SetcontentOffet and every other possiblities.
-(void)ScrollToPage:(int)page
{
UIViewController *controller = [self.childViewControllers objectAtIndex:page];
if (controller.view.superview == nil)
{
CGRect frame = self.scrollView.frame;
if (frame.size.width == 0)
{
frame.size.width = self.view.frame.size.width;
frame.size.height = self.view.frame.size.height;
}
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView setContentOffset:CGPointMake(frame.origin.x, frame.origin.y) animated:YES];
self.pageControl.currentPage = page;
[self centerScrollViewContents];
[self.scrollView setContentOffset:CGPointMake(frame.origin.x, frame.origin.y)];
[self.scrollView scrollRectToVisible:frame animated:YES];
[self.scrollView addSubview:controller.view];
}
}
I assume that your pages are using your device width closely. Just follow the below steps.
- (void)viewWillAppear:(BOOL)animated {
self.myCurrentPage = 0;
[self setScrollViewPages];
self.scrollView.delegate = self;
}
- (void)setScrollViewPages {
for (int i = 0; i < numberOfPages; i++) {
UIView *myPageView = [[UIView alloc]initWithFrame:(CGRect) {self.view.frame.size.width * i
+ 10.0f,10.0f,self.view.frame.size.width - 20.0f , self.scrollView.frame.size.height-20.0f}];
myPageView.backgroundColor = [UIColor greenColor];
[self.scrollView addSubview:myPageView];
}
}
On Button Clicked
- (IBAction)buttonClicked:(id)sender {
//Pass the requried page, by default I'm passing 4
self.myCurrentPage = 4;
[self updateMyScrollView];
}
And the respective scroll view setting is
- (void)updateMyScrollView {
[self.scrollView setContentOffset:CGPointMake(self.view.frame.size.width *self.myCurrentPage, 0) animated:YES];
self.pageControl.currentPage = self.myCurrentPage;
}
Additionally, your scrollview delegate would be like this...
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
int pageWidth = self.view.frame.size.width ;
int pageX = self.myCurrentPage*pageWidth - scrollView.contentInset.left;
if (targetContentOffset->x<pageX) {
if (self.myCurrentPage>0) {
self.myCurrentPage--;
}
}
else if(targetContentOffset->x>pageX){
if (self.myCurrentPage < numerOfPages) {
self.myCurrentPage++;
}
}
targetContentOffset->x = self.myCurrentPage*pageWidth-scrollView.contentInset.left;
DLog(#"%ld %d", (long)self.myCurrentPage, (int)targetContentOffset->x);
self.pageControl.currentPage = self.myCurrentPage;
}
Hope this helps....
I did my Top View and Bottom View (UIViews) hide while the UITableView is scrolling. Now, I need to check if the user begin drag the UITableview to up again and back the uiviews for the initial position. I have the following code to do the first step: hidden/show while scrolling uitableview
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(!self.isScrollingFast) {
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
CGFloat screenHeight = screenSize.height;
NSInteger yOffset = scrollView.contentOffset.y;
if (yOffset > 0) {
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.originalFrame.origin.y + yOffset, self.tabBar.frame.size.width, self.tabBar.frame.size.height);
self.viewTopo.frame = CGRectMake(self.viewTopo.frame.origin.x, self.originalFrameTopo.origin.y - yOffset, self.viewTopo.frame.size.width, self.viewTopo.frame.size.height);
if(self.originalFrameHidingView.origin.y - yOffset >= 0) {
self.hidingView.frame = CGRectMake(self.hidingView.frame.origin.x, self.originalFrameHidingView.origin.y - yOffset, self.hidingView.frame.size.width, self.hidingView.frame.size.height);
}
else {
self.hidingView.frame = CGRectMake(self.hidingView.frame.origin.x, -10, self.hidingView.frame.size.width, self.hidingView.frame.size.height);
}
[self.tbPertos setFrame:CGRectMake(self.tbPertos.frame.origin.x, self.hidingView.frame.origin.y + self.hidingView.frame.size.height, self.tbPertos.frame.size.width, self.tbPertos.frame.size.height)];
if(self.tbPertos.frame.size.height + self.tbPertos.frame.origin.y + yOffset <= screenHeight)
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.tbPertos.frame.origin.y, self.tbPertos.frame.size.width, self.tbPertos.frame.size
.height+yOffset);
else {
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.tbPertos.frame.origin.y, self.tbPertos.frame.size.width, screenHeight - self.tbPertos.frame.origin.y);
}
}
if (yOffset < 1) {
self.tabBar.frame = self.originalFrame;
self.viewTopo.frame = self.originalFrameTopo;
self.hidingView.frame = self.originalFrameHidingView;
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.hidingView.frame.origin.y + self.hidingView.frame.size.height, self.tbPertos.frame.size.width, screenHeight - self.tbPertos.frame.origin.y);
}
}
}
And there's the code which I'm trying to do the Top and Bottom View reappear when the user begin scroll up. Independently wheres the scroll offset.
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
CGPoint currentOffset = scrollView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - self.lastOffsetCapture;
CGFloat distance = currentOffset.y - self.lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
if (distance < 0) {
if(!self.isScrollingFast) {
NSLog(#"voltar posicao normal");
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.tabBar.frame = self.originalFrame;
self.viewTopo.frame = self.originalFrameTopo;
self.hidingView.frame = self.originalFrameHidingView;
self.tbPertos.frame = self.originalFrameTbPertos;
self.isScrollingFast = YES;
[UIView commitAnimations];
}
} else {
self.isScrollingFast = NO;
}
self.lastOffset = currentOffset;
self.lastOffsetCapture = currentTime;
}
Here i implemented code for UIView Hide / Show when tableview scrolling. When tableview scrolling down then UIView is hidden and when scrolling up then UIView show. I hope it's working for you...!
Step 1:- Make one property in .h file
#property (nonatomic) CGFloat previousContentOffset;
Step 2:- Write down this code in scrollViewDidScroll Method.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat currentContentOffset = scrollView.contentOffset.y;
if (currentContentOffset > self.previousContentOffset) {
// scrolling towards the bottom
[self.subButtonView setHidden:YES];
} else if (currentContentOffset < self.previousContentOffset) {
// scrolling towards the top
[self.subButtonView setHidden:NO];
}
self.previousContentOffset = currentContentOffset;
}
Hi I'm trying to create this kind of layout for my app.
So as you can see from the image UICollectionView has to move to the right of the screen and change in size. Also all the UIViews change in size when orientation changes.
I have tried to change the location of the elements in the code and then call that method whenever the view appears:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
// portrait
[self portraitUISetup];
} else {
// landscape
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(landscapeUISetup)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
}
-(void)portraitUISetup
{
self.flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.flowLayout.minimumLineSpacing = 18.0f;
self.flowLayout.itemSize = CGSizeMake(167, 254);
self.flowLayout.sectionInset = UIEdgeInsetsMake(18, 40, 52, 18);
CGRect rect = self.textView.frame;
rect.size.width = 355;
rect.size.height = 438;
rect.origin.x = 373;
rect.origin.y = 230;
self.textView.frame = rect;
rect = self.collectionView.frame;
rect.size.width = 768;
rect.size.height = 327;
rect.origin.x = 0;
rect.origin.y = 697;
self.collectionView.frame = rect;
rect = self.slideshow.frame;
rect.size.width = 768;
rect.size.height = 181;
rect.origin.x = 0;
rect.origin.y = 20;
self.slideshow.frame = rect;
rect = self.selectedIssueCover.frame;
rect.size.width = 293;
rect.size.height = 438;
rect.origin.x = 40;
rect.origin.y = 230;
self.selectedIssueCover.frame = rect;
}
-(void)landscapeUISetup
{
self.flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.flowLayout.minimumLineSpacing = 49.0f;
self.flowLayout.itemSize = CGSizeMake(167, 254);
self.flowLayout.sectionInset = UIEdgeInsetsMake(18, 23, 0, 25);
self.collectionView.alwaysBounceHorizontal = NO;
CGRect rect = self.collectionView.frame;
rect.size.width = 217;
rect.size.height = 539;
rect.origin.x = 810;
rect.origin.y = 229;
self.collectionView.frame = rect;
rect = self.slideshow.frame;
rect.size.width = self.view.bounds.size.width;
rect.size.height = 181;
rect.origin.x = 0;
rect.origin.y = 20;
self.slideshow.frame = rect;
rect = self.selectedIssueCover.frame;
rect.size.width = 333;
rect.size.height = 498;
rect.origin.x = 40;
rect.origin.y = 233;
self.selectedIssueCover.frame = rect;
rect = self.textView.frame;
rect.size.width = 355;
rect.size.height = 498;
rect.origin.x = 414;
rect.origin.y = 233;
self.textView.frame = rect;
}
The problem I have encountered with this method is that as soon as I push to another view this view is reset to the portrait one(probably to the one set in the storyboard) even if the device is in landscape.
So what would the right way to do this?
Put your layout logic inside viewWillLayoutSubviews instead of registering for rotation events.
If you are using Interface Builder it's really easy to setup two different layouts based on the size class. If you change your simulated metrics at the bottom from wAny hAny to wRegular hAny and setup some new layout constraints it will automatically switch between the two at run time.
Ok the problem was with the interface check. I changed that a little and used #Ian MacDonald's suggestions to use viewDidLayoutSubviews
Here is my solution that works now.
-(void)viewDidLayoutSubviews
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self landscapeUISetup];
} else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
[self portraitUISetup];
}
}
The correct way to do this is with UICollectionViewFlowLayoutInvalidationContext. See How to invalidate flow collection view layout on rotation for a sample implementation:
http://aplus.rs/2015/how-to-invalidate-flow-collection-view-layout-on-rotation/
To-wit:
Say you want to have grid layout with cells always half the size of the screen’s width. You want to maintain that layout in both portrait and landscape. Since iOS 8 that can’t be easier, with the right incantations.
First, subclass UICollectionViewFlowLayout; then, add the following method to it:
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds {
UICollectionViewFlowLayoutInvalidationContext *context = (UICollectionViewFlowLayoutInvalidationContext *)[super invalidationContextForBoundsChange:newBounds];
context.invalidateFlowLayoutDelegateMetrics = (
CGRectGetWidth(newBounds) != CGRectGetWidth(self.collectionView.bounds) ||
CGRectGetHeight(newBounds) != CGRectGetHeight(self.collectionView.bounds)
);
return context;
}
The key here is casting returned context from super as UICollectionViewFlowLayoutInvalidationContext which allows you to toggle the invalidateFlowLayoutDelegateMetrics property. That will tell UIKit that it should re-query FlowLayout’s delegate for the sizes.
In the collection view controller, make sure it’s set to adopt UICollectionViewDelegateFlowLayout protocol and then add this delegate call:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewFlowLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(floor(self.view.bounds.size.width/2.0), 88);
}
This is my code
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if ([[UIScreen mainScreen] bounds].size.height == 568) {
webview.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"tripadvisorwaiting5.png"]];
CGRect frame = webview.frame;
frame.size.width = 320;
frame.size.height = 568;
webview.frame = frame;
}
else {
webview.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"tripadvisorwaiting.png"]];
CGRect frame = webview.frame;
frame.size.width = 320;
frame.size.height = 480;
webview.frame = frame;
}
}
else {
webview.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"tripadvisorwaitingipad.png"]];
CGRect frame = webview.frame;
frame.size.width = 768;
frame.size.height = 1024;
webview.frame = frame;
}
but when the page loads, the image is too big or too small, and it's not scaled depending on the device.
Can you help me?
I believe +colorWithPatternImage sizes the image to the frame at the time you call it, so resizing the frame after calling webview.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"tripadvisorwaiting5.png"]]; would have no effect on scaling the image. Try setting the background image after you set the frame size. For instance:
if ([[UIScreen mainScreen] bounds].size.height == 568) {
CGRect frame = webview.frame;
frame.size.width = 320;
frame.size.height = 568;
webview.frame = frame;
webview.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"tripadvisorwaiting5.png"]];
}
I am trying to show UIPickerView on click on UITextField. I am using a simple method to show the picker as follows:
-(void) showPickerView {
[self.view resignFirstResponder];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.50];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if(iOSDeviceScreenSize.height == 480){
CGRect frame = self.picker.frame;
frame.origin.y = 270;
self.picker.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = 226.0;
self.toolBar.frame = frame;
} else if(iOSDeviceScreenSize.height == 568){
CGRect frame = self.picker.frame;
frame.origin.y = 239.0;
self.picker.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = 195.0;
self.toolBar.frame = frame;
}
[UIView commitAnimations];
}
It works great if I have not scrolled down. But when I scroll down, my picker is placed on fix position as mentioned in showPickerView method. Now how I can manage it that my picker appears at bottom every time.
Solution 1:
Add your pickerview to your window.
Solution 2:
Implement the scrollview delegate and adjust the frame continuously.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if(iOSDeviceScreenSize.height == 480){
CGRect frame = self.picker.frame;
frame.origin.y = 270;
self.picker.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = 226.0;
self.toolBar.frame = frame;
} else if(iOSDeviceScreenSize.height == 568){
CGRect frame = self.picker.frame;
frame.origin.y = 239.0;
self.picker.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = 195.0;
self.toolBar.frame = frame;
}
}
I can just suppose that you are showing your picker inside of a scroll view, right?
And if so, then your picker frame is relative to UIScrollView, not to a screen view.
So you have to take into account your scroll view offset. Something like that:
CGRect frame = self.picker.frame;
frame.origin.y = self.scrollvew.contentOffset.y + 270;
Otherwise you can show your picker outside of the UIScrollView (just add it to a screen view).