查找未被 UINavigationBar、UITabBar 等遮挡的 UIViewController 视图的边界
Find bounds of UIViewController's view not obscured by UINavigationBar, UITabBar, (etc)
我可以配置我的 UIViewController
的 edgesForExtendedLayout
,使其扩展到导航栏或标签栏等内容下方。如果我这样做,是否有某种方法可以确定未被遮挡的帧?
作为一种可能的替代方法,UIViewController
是否可以确定默认的 contentInset 以应用于它包含的 UIScrollView
?
用例
我有包含图像的可缩放 UIScrollView。
当它完全缩小时,我想调整内容插入,让内容保持居中 (details here)。但是,我修改的插图没有考虑 UIViewController
自动应用的插图,因此其内容不会被导航栏等遮挡。
我还需要计算内容的最小缩放比例——整个图像可见且不被遮挡的缩放比例。要计算这个,我需要知道内容视图未被遮挡的部分的大小。
你需要这个
-(CGRect) unobscuredBounds
{
CGRect bounds = [self.view bounds];
return UIEdgeInsetsInsetRect(bounds, [self defaultContentInsets]);
}
-(UIEdgeInsets) defaultContentInsets
{
const CGFloat topOverlay = self.topLayoutGuide.length;
const CGFloat bottomOverlay = self.bottomLayoutGuide.length;
return UIEdgeInsetsMake(topOverlay, 0, bottomOverlay, 0);
}
您可以将它放在 category 中以便于重复使用。
这些方法正确处理了视图在旋转后调整大小时发生的变化——正确处理了 UINavigationBar 大小的变化。
内容居中
要将其用于 centre content by adjusting insets,您需要执行以下操作:
-(void) scrollViewDidZoom:(UIScrollView *)scrollView
{
[self centerContent];
}
- (void)centerContent
{
const CGSize contentSize = self.scrollView.contentSize;
const CGSize unobscuredBounds = [self unobscuredBounds].size;
const CGFloat left = MAX(0, (unobscuredBounds.width - contentSize.width)) * 0.5f;
const CGFloat top = MAX(0, (unobscuredBounds.height - contentSize.height)) * 0.5f;
self.scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);
}
您的内容插图现在将反映他们需要的默认插图(以避免被掩盖),并且还将具有需要很好地居中的插图。
处理旋转和缩放
您可能还想在横向和纵向之间设置动画时执行居中。同时,您可能想要调整最小缩放比例,以便您的内容始终适合。尝试这样的事情:
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self centerContent];
const bool zoomIsAtMinimum = self.scrollView.zoomScale == self.scrollView.minimumZoomScale;
self.scrollView.minimumZoomScale = [self currentMinimumScale];
if(zoomIsAtMinimum)
{
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}
}
-(CGFloat) currentMinimumScale
{
const CGFloat currentScale = self.scrollView.zoomScale;
const CGSize scaledContentSize = self.scrollView.contentSize;
const CGSize scrollViewSize = [self unobscuredBounds].size;
CGFloat scaleToFitWidth = currentScale * scrollViewSize.width / scaledContentSize.width;
CGFloat scaleToFitHeight = currentScale * scrollViewSize.height / scaledContentSize.height;
return MIN(scaleToFitWidth, scaleToFitHeight);
}
willAnimateRotationToInterfaceOrientation:…
方法在视图动画块中调用,因此当您从横向切换到纵向时,它应用的更改将导致漂亮的平滑动画更改。
我可以配置我的 UIViewController
的 edgesForExtendedLayout
,使其扩展到导航栏或标签栏等内容下方。如果我这样做,是否有某种方法可以确定未被遮挡的帧?
作为一种可能的替代方法,UIViewController
是否可以确定默认的 contentInset 以应用于它包含的 UIScrollView
?
用例
我有包含图像的可缩放 UIScrollView。
当它完全缩小时,我想调整内容插入,让内容保持居中 (details here)。但是,我修改的插图没有考虑 UIViewController
自动应用的插图,因此其内容不会被导航栏等遮挡。
我还需要计算内容的最小缩放比例——整个图像可见且不被遮挡的缩放比例。要计算这个,我需要知道内容视图未被遮挡的部分的大小。
你需要这个
-(CGRect) unobscuredBounds
{
CGRect bounds = [self.view bounds];
return UIEdgeInsetsInsetRect(bounds, [self defaultContentInsets]);
}
-(UIEdgeInsets) defaultContentInsets
{
const CGFloat topOverlay = self.topLayoutGuide.length;
const CGFloat bottomOverlay = self.bottomLayoutGuide.length;
return UIEdgeInsetsMake(topOverlay, 0, bottomOverlay, 0);
}
您可以将它放在 category 中以便于重复使用。
这些方法正确处理了视图在旋转后调整大小时发生的变化——正确处理了 UINavigationBar 大小的变化。
内容居中
要将其用于 centre content by adjusting insets,您需要执行以下操作:
-(void) scrollViewDidZoom:(UIScrollView *)scrollView
{
[self centerContent];
}
- (void)centerContent
{
const CGSize contentSize = self.scrollView.contentSize;
const CGSize unobscuredBounds = [self unobscuredBounds].size;
const CGFloat left = MAX(0, (unobscuredBounds.width - contentSize.width)) * 0.5f;
const CGFloat top = MAX(0, (unobscuredBounds.height - contentSize.height)) * 0.5f;
self.scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);
}
您的内容插图现在将反映他们需要的默认插图(以避免被掩盖),并且还将具有需要很好地居中的插图。
处理旋转和缩放
您可能还想在横向和纵向之间设置动画时执行居中。同时,您可能想要调整最小缩放比例,以便您的内容始终适合。尝试这样的事情:
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self centerContent];
const bool zoomIsAtMinimum = self.scrollView.zoomScale == self.scrollView.minimumZoomScale;
self.scrollView.minimumZoomScale = [self currentMinimumScale];
if(zoomIsAtMinimum)
{
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}
}
-(CGFloat) currentMinimumScale
{
const CGFloat currentScale = self.scrollView.zoomScale;
const CGSize scaledContentSize = self.scrollView.contentSize;
const CGSize scrollViewSize = [self unobscuredBounds].size;
CGFloat scaleToFitWidth = currentScale * scrollViewSize.width / scaledContentSize.width;
CGFloat scaleToFitHeight = currentScale * scrollViewSize.height / scaledContentSize.height;
return MIN(scaleToFitWidth, scaleToFitHeight);
}
willAnimateRotationToInterfaceOrientation:…
方法在视图动画块中调用,因此当您从横向切换到纵向时,它应用的更改将导致漂亮的平滑动画更改。