原文链接:
http://the.ichibod.com/kiji/always-constrain-a-view-controller-to-portrait-or-landscape-orientation/
Interesting problem: most of your app allows for any orientation, however one specific view controller is picky and can only be either of the portrait (or landscape) orientations. When switching to this picky view collection, the view is displayed incorrectly and then rotates, though it still is displayed incorrectly.
There is a fix to constrain one view controller to an orientation when switching between controllers in an app and I am sure this is one of many solutions. This was utilized in an iPad app for iOS 4.3.
The Plan
The example code below is meant to be implemented in a view controller (and could be implemented with more work in a UIView). The idea is to rotate the view 90 degrees before it displayed on screen, if it is coming from a landscape orientation and the view can only be portrait specifically. When the view is rotated to portrait, then we want to remove the rotation and assign it back to zero.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
Despite being constrained to only the two portrait orientations in the code above, the view is still attempted to be displayed in landscape orientation (at least in my experience).
Step One
The first step is setting up the viewWillAppear: method in the view controller. This will be called before the view controller appears and is rendered on screen.
- (void)viewWillAppear:(BOOL)animated {
CGAffineTransform rotateTransform;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIDeviceOrientationLandscapeLeft:
rotateTransform = CGAffineTransformMakeRotation(-90*M_PI/180.0);
break;
case UIDeviceOrientationLandscapeRight:
rotateTransform = CGAffineTransformMakeRotation(90*M_PI/180.0);
break;
default:
rotateTransform = CGAffineTransformMakeRotation(0);
break;
}
rotateTransform = CGAffineTransformTranslate(rotateTransform, +90.0, +90.0);
[self.view setTransform:rotateTransform];
}
The device orientation is determined by [UIApplication sharedApplication].statusBarOrientation. At this time, the device orientation data found at [[UIDevice currentDevice] orientation] I have found to be unreliable at the point in which viewWillAppear: is called. Therefore the statusBarOrientation is utilized. Before the view appears, the orientation is used to determine if the device is in one of the two landscape orientations and the view’s transform property is assigned the rotated transformation object that is created. All of this will rotate the view, even though the view controller thinks it is in the landscape orientation, and display it in the portrait orientation.
Step Two
The second (and last) is to implement the willRotateToInterfaceOrientation:duration: method in your controller. This method is called on a view controller immediately before the interface is about to rotate. The following code will determine if we have already rotated the view, and need to reset it before we rotate to the orientation we are looking for.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
CGAffineTransform t = self.view.transform;
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation) && t.b && t.c) {
[self.view setTransform:CGAffineTransformMakeRotation(0)];
}
}
The code above is simple. It retrieves the view’s transform information and determines if b and c in the transform matrix are both not equal to or less than 0, otherwise the view has a rotation transformation applied. Then proceeds to reset the views transform rotation to the default of 0.
Small Glitch
There is a small visual glitch that is created because of this process. The view controller and orient itself and respond to the shouldAutorotateToInterfaceOrientation: that is set in the code above. However, the controller will still think it requires a rotation so the black areas on the corners will be displayed as if the the orientation was changing. It is changing, however the view is not, because when it rotates the CGAffineTransformMakeRotation(0) is resetting it, so visually the content stays in the same position. Small, though possibly a deal breaker for some as a worthwhile solution.
I mentioned before there are probably other solutions to this problem, this one seemed to work for me. Let me know if you find any other easier ways to do this in the comments.
分享到:
相关推荐
通过定义约束,你可以确保视图在横竖屏下都能正确显示。 4. **Storyboard或Xib文件**:在Storyboard或Xib文件中,可以通过选择View Controller的Size Inspector来设置其支持的界面方向。此外,针对不同方向创建不同...
在`AndroidManifest.xml`中,可以通过`android:configChanges`属性指定Activity如何处理配置变更。例如,设置`android:configChanges="orientation|screenSize"`可以使Activity不被销毁,而是直接调用`...
- 重写BaseAdapter涉及的主要方法有`getCount()`返回数据项数量,`getItem(int position)`获取指定位置的数据,`getView(int position, View convertView, ViewGroup parent)`负责视图的创建与复用。 - 为了提高...
- 通过分节符,你可以让指定页面的页码从1开始重新计数。 - 分节符还允许你在不同节内创建独特的页眉和页脚,增强文档的结构和可读性。 了解并熟练运用这些技巧,将有助于你在处理Word文档时更加灵活和高效,特别是...
3. 性能优化:频繁的横竖屏切换可能会导致性能问题,因为系统需要重新加载布局和计算视图。合理的设计和优化,如延迟非必要操作,减少视图层次,以及使用约束布局等,可以帮助提升性能。 四、用户交互和体验 1. ...
这个"横竖屏显示IOS例子程序"(TestDemo)就是针对这一需求的实例代码,帮助我们理解和实现横竖屏切换以及指定界面横屏显示的功能。 首先,让我们了解iOS中处理屏幕方向的基本概念。在iOS中,屏幕方向主要分为两种...
这个"RotateDemo"项目很可能包含了一个简单的应用,其中至少有两个视图控制器,分别展示如何在代码中处理横竖屏切换。通过查看和学习这个示例,开发者可以理解如何根据业务需求灵活控制iOS应用中的屏幕方向。 总之...
1. 使用`android:configChanges="orientation|screenSize"`属性,在AndroidManifest.xml中指定Activity对横竖屏变化的处理方式,让系统不再默认销毁Activity。 2. 在Activity中重写`onConfigurationChanged...
- `android:layout_alignBaseline`: 当前视图的基线与指定id视图的基线对齐。 - `android:layout_alignBottom`: 当前视图的下边界与指定id视图的下边界对齐。 - `android:layout_alignLeft`: 当前视图的左边界与指定...
在这个"swift-可横竖向切换的瀑布流布局"项目中,开发者实现了一个可以横竖向切换的瀑布流视图,为用户提供更灵活的界面体验。 首先,我们来了解一下瀑布流布局的基本原理。瀑布流布局的核心在于计算每个单元格...
`preferredInterfaceOrientationForPresentation`方法用于指定在全屏模式下应用首选的界面方向。对于播放器,你可能希望在全屏模式下选择横屏方向。 6. **手势控制**: 描述中提到的“左右滑动手势快进”是另一个...
- `getItem(int position)`: 获取指定位置的条目数据。 - `getItemId(int position)`: 返回条目的唯一ID,通常用位置作为ID。 - `getView(int position, View convertView, ViewGroup parent)`: 这是最重要的方法...
1. 对于不希望改变屏幕方向的App,可以在Manifest中指定Activity的屏幕方向,如`android:screenOrientation="portrait"`或`android:screenOrientation="landscape"`。 六、横竖屏切换的最佳实践 - 使用Fragment...
5. **SwiftUI**:在SwiftUI中,我们可以使用`.frame(minWidth: _, maxWidth: _, minHeight: _, maxHeight: _)`来指定视图的尺寸范围,并使用`.geometryReader`来获取内容的大小,进而实现高度自适应。 总的来说,...
6. **视频渲染**:AVPlayerLayer是AVPlayer的一个重要组件,它可以将视频内容渲染到指定的CALayer上,从而在屏幕上显示出来。在横竖屏切换时,可能需要调整AVPlayerLayer的frame以适应新的屏幕尺寸。 7. **音量和...
通过设置`android:columnCount`和`android:rowCount`,可以定义网格的列数和行数,而`android:layout_column`和`android:layout_row`则用于指定控件所在的位置。 接下来是`LinearLayout`,它是Android中最基础也是...
Size Classes则允许开发者为不同类型的设备和横竖屏指定不同的布局。 此外,`UIStackView`是iOS9引入的新特性,它简化了多个视图水平或垂直堆叠的布局。通过UIStackView,开发者可以方便地调整子视图的排列、间距和...
2. **使用ViewStub**:在Activity中使用`ViewStub`控件替换部分复杂的视图,只在需要时才实例化并显示这些视图。 3. **异步加载数据**:在Activity创建时,通过异步线程加载数据,避免阻塞UI线程。 4. **使用...
在传统的Android布局中,我们通常使用dp(density-independent pixels)作为单位来指定视图的宽高,但这在处理不同屏幕尺寸时可能会导致显示效果不一致。百分比布局解决了这个问题,它基于LinearLayout、...
对于每个视图,我们可以分别设置其在不同Size Class下的约束,这样就能确保界面在任何设备上都能保持良好的视觉效果。 在横屏和竖屏之间切换时,Size Classes会自动调整。iOS设备有两种主要的Size Classes:Regular...