Hi currently am working on a ipad app where i need to display the tableview. So we are displaying the tableview with a custom cell.Now the problem is when the application is in landscape mode there is a layout in my custom cell and when the app rotates to portrait mode the layout should be changed.Any help will be appreciated.
try this,
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
//your code for landscape
} else {
//your code for portrait
}
}
this may helps you.....
Related
i am working in a project in which i am using UITableView to display data. The orientation of my project is Landscape. now i want to add portrait orientation mode to my project so that any user can use app in portrait as well as in landscape mode.
Is there any code or method available by the help of which i will change the orientation of UITableView from horizontal to vertical??
i want the orientation something like this
Just develop 2 different prototypes with unique identifiers, provide them in cellForRowAtIndexPath based on current orientation.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
LatestNewsCell *cell = (LatestNewsCell *)[tableView dequeueReusableCellWithIdentifier:#"portraitCell" forIndexPath:indexPath];
// configure cell
return cell;
} else {
LatestNewsCell *cell = (LatestNewsCell *)[tableView dequeueReusableCellWithIdentifier:#"landscapeCell" forIndexPath:indexPath];
// configure cell
return cell;
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.tableView reloadData];
}
In the case of the cell with more labels, you just create additional IBOutlets for these and reuse the existing ones for the labels that are used in both orientations.
I believe you just need to setup your project to support portrait orientation. After that, your UITableView will rotate as you rotate your device or simulator.
I have created a simple project to test this. Check the output here.
Notice that sometimes, the view correctly rotates, and sometimes not. Must be a bug.
This is the view of the app when it is in portrait mode.
When it is rotated to landscape mode it looks like this
The view debugger shows that the UIWindow is not rotating as shown here
The UICollectionViewController is created via StoryBoard. I've tried subclassing UICollectionViewFlowLayout that implements shouldInvalidateLayoutForBoundsChange, but it does not fix my issue.
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
CGRect oldBounds = self.collectionView.bounds;
if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds)) {
return YES;
}
return NO;
}
Please provide ideas of what to check next or requests for additional code to debug.
Edit - As suggested by MirekE, I attempted to add constraints to the CollectionView but was unable. All of the options for Editor->Pin are unavailable for the CollectionView.
Edit, response to Andrea -
I'm targeting iOS8.3. My understanding is that the main method called at rotation is viewWillTransitionToSize:withTransitionCoordinator:, which is from the UIContentContainer protocol. I've added the following to my CollectionViewController, but same problem persists
-(void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator {
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView reloadData];
}
I don't know which iOS version you ara targeting, but let me suppose that you know the rotation process and methods called in the view controller while it's happening.
In one of those methods you just need to call:
[self.collectionView.collectionViewLayout invalidateLayout];
and maybe depending on your layout -reloadData
No need to subclass.
EDIT
I use this method, I guess that is not working because you should relayout the collection after it has resized:
- (void) willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self.collectionView.collectionViewLayout invalidateLayout];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self.collectionView reloadData];
}];
}
What I'm doing attach the layout invalidation process to the animation process.
If you have custom implementation of UICollectionViewLayout, try to override methods:
override public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
let bounds = self.collectionView!.bounds;
return ((CGRectGetWidth(newBounds) != CGRectGetWidth(bounds) ||
(CGRectGetHeight(newBounds) != CGRectGetHeight(bounds))));
}
override public func invalidateLayout() {
cache.removeAll() // remove layout attributes ans settings if they exist
super.invalidateLayout()
}
Cheers !
It looks like you just drag the collection view on the canvas, but did not add any constraints. So when you rotate the device, the size does not change.
In the storyboard select the collection view, then click on the Pin icon at the bottom of Xcode and add constraints for the top, left, bottom and right margins. After you do that, the collection view should resize on rotation.
The problem was that the collectionView outlet was not properly set. After setting the collectionView, all works properly.
collectionView outlet not set:
collectionView outlet set:
I'm working on an application that should support both portrait and landscape orientations. There is no problem with using auto layout for re arranging the controls in the view but there is something that i cannot do with auto layout. I have two views under each other in the portrait view and i want them to be next to each other in landscape view. I can move the bottom view in the right X position but it is still under the top view. this picture describes what i want to do:
http://www.hesamstore.ir/Orient.png
How Can I Do This?
Thanks for reading.
Add constraints to all the IBOutlets.
add Constraints - 1. Height,width, Trailing and leading , and that would solve it,
If you want accurate ratio then select two outlets and add horizontal constraints with a ratio.
And also select a label and its corresponding switch and add horizontal spacing and do it to EQUAL.
Yup that should do it.
just implements this method to your code...
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
BOOL isPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
if(isPortrait == NO)
{
// this is landScape mode....
// here give the frames that you want for your controls...
}
if(isPortrait == YES)
{
// this is portrait mode....
// here give the frames that you want for your controls...
}
}
I have two different UIViewControllers, and both of them have UiCollectionView.
Problems appears when I try rotate iPad.
Next I have in portrait position
When I rotate to landscape I reload my collectionView, so in lanscape mode I need have 3 columns
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self.collectionView reloadData];
}
In first viewController all good, and when collectionView begin rotate controller still have 3 columns
But when I try do it in another controller, I get bad situation
It is looks like in one moment two collectionView in my view, and then one of them is disappearing.
I use standart UICollectionViewFlowLayout and have same methods for buils layout
Have you tried invoking the view..
(void)invalidateLayout
You can call this method at any time to update the layout information. This method invalidates the layout of the collection view itself and returns right away. Thus, you can call this method multiple times from the same block of code without triggering multiple layout updates. The actual layout update occurs during the next view layout update cycle.
Have you also tried this?
(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
[self.collectionView reloadData];
}
I think I have solution, try this which understands when animating the rotation;
(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:( NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.collectionView reloadData];
}
On the iPad I show a UIPopover when the user selects cells in a UITableView. The cell stays selected until the popover is dismissed.
When the user rotates the device from portrait to landscape orientation and the selected cell was on the lower part of the screen, it will disappear after the rotation and the popover ends up pointing at another (indifferent) cell.
How can I make sure that the selected cell in a UITableView stays on screen when rotating from portrait to landscape orientation?
Update: Combining Caleb's and kviksilver's codes, the following is a working solution:
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
CGRect activeCellRect = [self.tableView rectForRowAtIndexPath:self.indexPath];
if ((activeCellRect.origin.y + activeCellRect.size.height) >
(self.view.frame.origin.y + self.view.frame.size.height))
{
// If a row ends up off screen after a rotation, bring it back
// on screen.
[self.tableView scrollToRowAtIndexPath:self.indexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
}
Update 2, on repositioning the UIPopover: After the scroll command it is necessary to send a reloadData message to the table view. Then the rectForRowAtIndexPath: method will correctly report the new position of the cell (otherwise it will not, as it is not updated properly after the scroll-command)!
On orientation change try checking indexPathsForVisibleRows to see if your cell is visible and then using scrollToRowAtIndexPath if not.. something like:
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
if (![[self.tableView indexPathsForVisibleRows] containsObject:[self.tableView indexPathForSelectedRow]]) {
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForSelectedRow] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
}
You already know which row is selected, right? You also know when the device orientation changes, or at least you can know that, because there are UIViewController methods for that. You can get the rectangle for the selected row using UITableView's -rectForRowAtIndexPath: method, and it's easy to make sure that rectangle stays visible using UIScrollView's -scrollRectToVisible:animated: method, which UITableView inherits.