我有一个UIViewController
子类作为故事板中的一个场景,其中包含一个包含各种子视图的UIScrollView
。其中一个子视图是UIButton
,它分割成另一个场景UIViewController
子类。当我从视图中返回时(从导航控制器堆栈中弹出UIViewController
),我发现滚动视图的原点已经有所改变,尽管contentsize
和contentoffset
似乎是正确的。 / p>
有趣的是,该应用程序有一个标签栏,当我离开并返回到该视图时,滚动视图正确设置,偏移量为(0,0)。
这个过程基本上没有涉及代码,因为它几乎都在故事板中。由于我对使用故事板相当新,我觉得我做错了什么,虽然我不知道是什么。关于那可能是什么的任何想法?也许是调整问题或限制?
答案 0 :(得分:92)
在iOS 7/8/9中,简单的self.automaticallyAdjustsScrollViewInsets = NO;
解决了我的问题。
答案 1 :(得分:30)
在弹出的视图控制器的viewWillAppear中尝试此操作:
self.scrollView.contentOffset = CGPointMake(0, 0);
编辑:在添加彼得的代码时,您可以获得最佳效果:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
self.scrollView.contentOffset = CGPointMake(0, 0);
}
加
- (void)viewWillDisappear:(BOOL)animated {
self.recentContentOffset = self.scrollView.contentOffset;
[super viewWillDisappear:animated];
}
和
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.scrollView.contentOffset = CGPointMake(0, self.recentContentOffset.y);
}
返回到原始滚动位置,没有视觉副作用,回滚后滚动视图本身在其超级视图中正确定位(这是一个问题)。
答案 2 :(得分:11)
实际上,我把这行代码放在viewDidDisappear
中,以便在视图重新出现时记住偏移量,我在它之前添加了这行
self.contentOffset = self.scrollView.contentOffset;
以及
- (void)viewDidLayoutSubviews {
self.scrollView.contentOffset = self.contentOffset;
}
答案 3 :(得分:5)
我遇到了类似的问题,在解除了一个viewController后,我的tableView中的contentOffset被改为(0,-64)。
我的解决方案有点奇怪,我尝试了所有其他答案但没有成功,解决我的问题的唯一办法就是在.xib的控件树中切换tableView位置
它是父视图中的第一个控件,如下所示:
我在ImageView之后移动了tableView,它运行起来了:
似乎将表格视图放在第一个位置会导致麻烦,并将表格视图移动到另一个位置可以解决问题。
Pd积。我没有使用autoLayout和故事板
希望这可以帮助别人!答案 4 :(得分:5)
我正在使用collectionView,我遇到了类似的问题。对于iOS 11:在尺寸检查器中,有“内容插入”。将其设置为“从不”。这解决了我的问题。我希望这可以帮助别人。
目标C:
if (@available(iOS 11, *)) {
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
夫特:
if #available(iOS 11, *) {
UIScrollView.appearance().contentInsetAdjustmentBehavior = .never
}
答案 5 :(得分:2)
在iOS 11中,我遇到了类似的问题,当我弹出一个视图控制器后回来时,前一个viewcontroller中的tableview用于自动调整其内容插入,导致tableview内容突然从顶部跳转。以下解决方案适用于iOS 11。
在Storyboard中,选择tableview并转到Attributes检查器,并取消选中Row Height和Estimate字段的“Automatic”。同时将内容插入从“自动”更改为“从不”。
[]
答案 6 :(得分:1)
不幸的是,Peter和MacMark的建议对我不起作用(Xcode 5 w / auto-layout)。解决方案是转到故事板,选择视图控制器和Reset to Suggested Constraints in View Controller
。
答案 7 :(得分:0)
只要以上方法均无济于事,我就会遇到这个问题,而对我来说,我遇到的是以下代码。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
注释此reloadData()行对我来说已解决此问题。我不需要此行,所以不确定为什么我还要添加它!
希望该解决方案可以帮助其他人。
答案 8 :(得分:0)
我在SO上随处可见了不同解决方案的组合,并提出了这个子类:
// Keeps track of the recent content offset to be able to restore the
// scroll position when a modal viewcontroller is dismissed
class ScrollViewWithPersistentScrollPosition: UIScrollView {
// The recent content offset for restoration.
private var recentContentOffset: CGPoint = CGPoint(x: 0, y: 0)
override func willMove(toWindow newWindow: UIWindow?) {
if newWindow != nil {
// save the scroll offset.
self.recentContentOffset = self.contentOffset
}
super.willMove(toWindow: newWindow)
}
override func didMoveToWindow() {
if self.window != nil {
// restore the offset.
DispatchQueue.main.async(execute: {
// restore it
self.contentOffset = self.recentContentOffset
})
}
super.didMoveToWindow()
}
}
在iOS 11.2 / Xcode 9.2上测试。
答案 9 :(得分:0)
以上都没有为我工作,我设法做了我自己的自定义推/拉动画,它就像一个魅力。
首先,添加实现Push方案的这个类
class PushAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// get reference to our fromView, toView and the container view that we should perform the transition in
let container = transitionContext.containerView
let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
// start the toView to the right of the screen
var frame = toView.frame
frame.origin.x = container.frame.width
toView.frame = frame
// add the both views to our view controller
container.addSubview(toView)
container.addSubview(fromView)
// get the duration of the animation
let duration = self.transitionDuration(using: transitionContext)
// perform the animation!
UIView.animate(withDuration: duration, animations: {
var frame = fromView.frame
frame.origin.x = -container.frame.width
fromView.frame = frame
toView.frame = container.bounds
}, completion: { _ in
// tell our transitionContext object that we've finished animating
transitionContext.completeTransition(true)
})
}
}
然后添加实现pop方案的这个类
import Foundation
import UIKit
class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// get reference to our fromView, toView and the container view that we should perform the transition in
let container = transitionContext.containerView
let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
// set up from 2D transforms that we'll use in the animation
let offScreenRight = CGAffineTransform(translationX: container.frame.width, y: 0)
// start the toView to the right of the screen
var frame = toView.frame
frame.origin.x = -container.frame.width
toView.frame = frame
// add the both views to our view controller
container.addSubview(toView)
container.addSubview(fromView)
// get the duration of the animation
let duration = self.transitionDuration(using: transitionContext)
// perform the animation!
UIView.animate(withDuration: duration, animations: {
fromView.transform = offScreenRight
toView.frame = container.bounds
}, completion: { _ in
// tell our transitionContext object that we've finished animating
transitionContext.completeTransition(true)
})
}
}
然后将此行添加到viewDidLoad方法以更改默认的NavigationController委托
self.navigationController?.delegate = self
看到魔术:)
答案 10 :(得分:0)
答案 11 :(得分:0)
尝试了很多事情之后:
我意识到问题是关于estimatedRowHeight
值,设置为50px,应该是~150px。更新值修复了问题,现在表视图保持相同的偏移量。
答案 12 :(得分:0)
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7) {
_isRecoredforios6 = YES;
_recordedOffsetforios6 = _scrollView.contentOffset;
_recordedSizeforios6 = _scrollView.contentSize;
_scrollView.contentOffset = CGPointZero;
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (_isRecoredforios6) {
_isRecoredforios6 = NO;
_scrollView.contentSize = _recordedSizeforios6;
_scrollView.contentOffset = _recordedOffsetforios6;
}
}
我已修复此ios6错误,可以使用这些代码解决。 我解决了Scrollview中发生的错误。 感谢所有朋友!
答案 13 :(得分:0)
最近,我遇到过这个bug,可以用这些代码解决:
// fix ios 6 bug begin
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7) {
isRecoredforios6 = YES;
recordedOffsetforios6 = self.tableView.contentOffset;
recordedSizeforios6 = self.tableView.contentSize;
}
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (isRecoredforios6) {
isRecoredforios6 = NO;
self.tableView.contentSize = recordedSizeforios6;
self.tableView.contentOffset = recordedOffsetforios6;
}
}
// fix ios 6 bug end
感谢Peter Jacobs!
答案 14 :(得分:0)
第二次尝试打开呈现的视图控制器,而没有离开呈现视图控制器,问题仍然存在。这就是我发布导致我的解决方案的确切步骤的原因。
因此,我在故事板中重置集合视图的约束,确保它们固定在呈现ViewController的主视图上。
在展示视图控制器的self.view.translatesAutoresizingMaskIntoConstraints = YES;
内添加了:viewDidLoad
。
存储,私下,在模式呈现的视图控制器外观之前的集合视图的contentOffset:
(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.contentOffset = self.collectionView.contentOffset;
self.collectionView.contentOffset = CGPointZero;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.collectionView.contentOffset = self.contentOffset;
}
答案 15 :(得分:0)
我最近发布了一个关于类似问题但在不同背景下的问题: Frame doesn't reflect auto layout constraints after dismissing modal view controller
在我的例子中,滚动视图内的自定义容器视图的原点是位移的,而不是滚动视图本身的原点。对于自动布局,自定义容器视图固定到滚动视图的四个边。
以编程方式而不是IB中创建和配置容器视图。尽管容器视图的约束未更改,但在解除模态视图控制器后,容器视图的原点将被替换。约束和框架之间的这种脱节是莫名其妙的。
更令人瞩目的是,在删除并重新添加所有相关约束之后,原始位移问题仍然存在。
我想出了一个类似的解决方案:保存当前内容偏移的值,将内容偏移设置为“零”,让系统交换您的视图,然后恢复内容偏移(即内容偏移舞蹈) )。
但就我而言,我不得不采取额外措施来解决问题。我的滚动视图是一个分页滚动视图,它从tilePages方法获取其子视图(在旧的WWDC视频中演示)。更改滚动视图的内容偏移量会通过UIScrollViewDelegate的scrollViewDidScroll:方法触发tilePages方法。当我做内容偏移舞时,我必须设置一个标志来关闭tilePages,否则应用程序会崩溃。
希望我升级到iOS 7时可以删除内容偏移舞蹈的代码。
答案 16 :(得分:-8)
否则关闭该xib的AutoLayout
选项。