您好,我正在尝试为我的应用创建这种布局。
因此,从图像中可以看出,UICollectionView必须移动到屏幕右侧并改变大小。当方向改变时,所有UIViews的大小也会发生变化。
我试图更改代码中元素的位置,然后在视图出现时调用该方法:
- (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;
}
问题我遇到过这种方法的问题是,只要我推送到另一个视图,此视图就会重置为纵向视图(可能是故事板中设置的视图),即使设备也是如此在风景中。
那么正确的方法是什么呢?
答案 0 :(得分:0)
将您的布局逻辑放在viewWillLayoutSubviews
内,而不是注册轮换事件。
答案 1 :(得分:0)
如果您正在使用Interface Builder,那么根据尺寸等级设置两种不同的布局非常容易。如果您将底部的模拟指标从wAny hAny
更改为wRegular hAny
并设置一些新的布局限制,则会在运行时自动在两者之间切换。
答案 2 :(得分:0)
好的问题是界面检查。我改变了一点,并使用@Ian MacDonald的建议来使用viewDidLayoutSubviews
这是我现在可以使用的解决方案。
-(void)viewDidLayoutSubviews
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self landscapeUISetup];
} else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
[self portraitUISetup];
}
}
答案 3 :(得分:0)
执行此操作的正确方法是使用UICollectionViewFlowLayoutInvalidationContext
。有关示例实现,请参见如何在轮换时使流集合视图布局无效:
http://aplus.rs/2015/how-to-invalidate-flow-collection-view-layout-on-rotation/
要-即:
假设您希望网格布局的单元格总是屏幕宽度的一半。您希望在纵向和横向中保持该布局。从iOS 8开始,用正确的咒语就不容易了。
首先,子类UICollectionViewFlowLayout
;然后,添加以下方法:
- (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;
}
这里的关键是将返回的上下文从super UICollectionViewFlowLayoutInvalidationContext
转换为允许您切换invalidateFlowLayoutDelegateMetrics
属性。这将告诉UIKit它应该重新查询FlowLayout的委托大小。
在集合视图控制器中,确保将其设置为采用UICollectionViewDelegateFlowLayout
协议,然后添加此委托调用:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewFlowLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(floor(self.view.bounds.size.width/2.0), 88);
}