UIViewController로 다시 팝업 된 후 UIScrollView의 원점이 변경됩니다.
다양한 하위보기 UIViewController
를 포함하는 스토리 보드의 장면 으로 하위 클래스가 UIScrollView
있습니다. 하위보기 중 하나는 UIButton
다른 장면 UIViewController
하위 클래스 로 연결되는 입니다. 내가보기에서 돌아올 때 (팝업 UIViewController
있지만, 나는 스크롤 뷰의 기원은 어떻게 든 변경된 것을 알게 탐색 컨트롤러 스택 오프) contentsize
및 contentoffset
올바른 보인다.
또한 흥미로운 점은 앱에 탭 바가 있고 탭에서 해당 뷰로 돌아갈 때 스크롤 뷰가 (0, 0) 오프셋으로 올바르게 다시 설정된다는 것입니다.
스토리 보드에 거의 모든 것이 있기 때문에 기본적으로이 프로세스에 관련된 코드는 없습니다. 나는 스토리 보드를 사용하는 데 상당히 익숙하기 때문에 나는 무엇을 모르지만 내가 뭔가 잘못하고 있다고 생각한다. 그것이 무엇인지에 대한 아이디어가 있습니까? 크기 문제 또는 제약 사항이 있습니까?
iOS 7/8/9에서는 self.automaticallyAdjustsScrollViewInsets = NO;
제 경우에 문제가 간단하게 해결되었습니다.
다시 팝업 뷰 컨트롤러의 viewWillAppear에서 이것을 시도하십시오.
self.scrollView.contentOffset = CGPointMake(0, 0);
편집 : Peter의 코드를 추가 할 때 다음과 같이 최상의 결과를 얻을 수 있습니다.
- (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);
}
원래 스크롤 위치로 돌아가고 시각적 부작용이 없으며 스크롤 뷰 자체가 다시 돌아온 후 수퍼 뷰 (문제)에 올바르게 배치됩니다.
사실, 저는 그 코드 줄을에 넣고 viewDidDisappear
뷰가 다시 나타날 때 오프셋을 기억하도록이 줄을 그 앞에 추가했습니다.
self.contentOffset = self.scrollView.contentOffset;
만큼 잘
- (void)viewDidLayoutSubviews {
self.scrollView.contentOffset = self.contentOffset;
}
비슷한 문제가 발생하여 viewController를 닫은 후 내 tableView의 contentOffset이 (0, -64)로 변경되었습니다.
내 솔루션은 약간 이상했습니다. 다른 모든 답변을 시도했지만 성공하지 못했습니다. 내 문제를 해결 한 유일한 방법은 .xib의 컨트롤 트리에서 tableView 위치를 전환하는 것입니다.
다음과 같은 상위 뷰의 첫 번째 컨트롤입니다.
ImageView 바로 뒤에 tableView를 옮겼고 작동했습니다.
테이블 뷰를 첫 번째 위치에 놓는 것이 문제를 일으키는 것으로 보이며 테이블 뷰를 다른 위치로 이동하면 문제가 해결되었습니다.
PD 나는 autoLayout도 스토리 보드를 사용하지 않는다
이것이 누군가를 도울 수 있기를 바랍니다!
collectionView를 사용하고 있는데 비슷한 문제가 있습니다. iOS 11의 경우 크기 검사기에 "내용 삽입"이 있습니다. "Never"로 설정하십시오. 그것은 나를 위해 문제를 해결했습니다. 누군가에게 도움이되기를 바랍니다.
목표 C :
if (@available(iOS 11, *)) {
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
빠른:
if #available(iOS 11, *) {
UIScrollView.appearance().contentInsetAdjustmentBehavior = .never
}
iOS 11에서는 뷰 컨트롤러를 띄운 후 돌아올 때 이전 뷰 컨트롤러의 테이블 뷰가 콘텐츠 삽입을 자동으로 조정하는 데 사용되어 테이블 뷰 콘텐츠가 갑자기 위쪽에서 점프하는 유사한 문제에 직면했습니다. 다음 솔루션은 iOS 11에서 저에게 효과적이었습니다.
Storyboard에서 tableview를 선택하고 Attributes inspector로 이동하여 Row Height 및 Estimate 필드에 대해 "자동"을 선택 취소하십시오. 또한 내용 삽입을 "자동"에서 "안함"으로 변경하십시오.
[ ]
불행히도 Peter와 MacMark의 제안은 저에게 효과가 없었습니다 (자동 레이아웃이있는 Xcode 5). 해결책은 스토리 보드로 이동하여 뷰 컨트롤러를 선택하고 Reset to Suggested Constraints in View Controller
.
최근 비슷한 문제에 대한 질문을 게시했지만 다른 맥락에서 : 모달 뷰 컨트롤러를 닫은 후 프레임이 자동 레이아웃 제약을 반영하지 않습니다.
제 경우에는 스크롤 뷰 자체의 원점이 아니라 스크롤 뷰 내부의 사용자 정의 컨테이너 뷰의 원점이 옮겨졌습니다. 자동 레이아웃과 관련하여 사용자 지정 컨테이너보기는 스크롤보기의 네면에 고정됩니다.
컨테이너보기는 IB가 아닌 프로그래밍 방식으로 생성 및 구성됩니다. 컨테이너보기의 제약 조건은 변경되지 않았지만 컨테이너보기의 원점은 모달보기 컨트롤러를 해제 한 후 대체됩니다. 제약과 프레임 사이의 이러한 단절은 설명 할 수 없습니다.
더욱 놀라운 점은 관련된 모든 제약을 제거하고 다시 추가 한 후에도 원점 변위 문제가 남아 있다는 것입니다.
비슷한 해결책을 찾았습니다. 현재 콘텐츠 오프셋 값을 저장하고 콘텐츠 오프셋을 "0"으로 설정 한 다음 시스템이 뷰를 교체하도록 한 다음 콘텐츠 오프셋을 복원합니다 (예 : 콘텐츠 오프셋 댄스).
그러나 제 경우에는 문제를 해결하기 위해 추가 조치를 취해야했습니다. 내 스크롤 뷰는 tilePages 메서드에서 하위 뷰를 가져 오는 페이징 스크롤 뷰입니다 (이전 WWDC 비디오에서 설명 됨). 스크롤 뷰의 콘텐츠 오프셋을 변경하면 UIScrollViewDelegate의 scrollViewDidScroll : 메서드를 통해 tilePages 메서드가 트리거됩니다. 콘텐츠 오프셋 댄스를하는 동안 tilePages를 끄는 플래그를 설정해야했습니다. 그렇지 않으면 앱이 충돌합니다.
iOS 7로 업그레이드 할 때 콘텐츠 오프셋 댄스에 대한 코드를 제거 할 수 있기를 바랍니다.
현재 답변을 따를 때 계속되는 문제 :
제시된 뷰 컨트롤러를 떠나지 않고 제시된 뷰 컨트롤러를 여는 두 번째 시도는 문제가 남아 있습니다. 이것이 내 솔루션을 가져온 정확한 단계 를 게시하는 이유 입니다.
따라서 Storyboard에서 collectionView의 제약 조건을 재설정 하여 이들이 고정 된 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; }
최근에이 버그가 발생했습니다. 다음 코드를 사용하여 해결할 수 있습니다.
// 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!
- (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에서 발생한 버그를 해결했습니다. 모든 친구들에게 감사합니다!
많은 것을 시도한 후 :
- 탐색 모음에 문제가 있는지 확인하려면 automaticAdjustsScrollViewInsets를 false로 설정하십시오.
- 고정 된 셀 높이로 재생 ...
- 셀 높이 캐싱 중 ...
- 테이블 뷰 오프셋으로 속성을 유지하고, 캐싱하고, viewWillAppear에 설정합니다.
- 기타
나는 estimatedRowHeight
그것이 ~ 150px이어야 할 때 50px로 설정된 값 에 관한 문제임을 깨달았습니다 . 값을 업데이트하면 문제가 해결되었으며 이제 테이블보기가 동일한 오프셋을 유지합니다.
불투명 막대 아래 가장자리 확장 옵션을 확인해 보셨습니까? 스토리 보드 내부의 컨트롤러 속성 검사기에서 찾을 수 있습니다.
XCode 9 iOS 11을 사용하여 나를 위해 트릭을 수행했습니다.
위의 어느 것도 나를 위해 일하지 않았고, 대신 내 사용자 지정 Push / Pull 애니메이션을 수행 할 수 있었고 매력처럼 작동합니다.
먼저 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)
})
}
}
그런 다음 팝 시나리오를 구현하는이 클래스를 추가하십시오.
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 Delegate를 변경합니다.
self.navigationController?.delegate = self
그리고 마술을보십시오 :)
나는 모든 곳에 게시 된 다양한 솔루션의 조합을 사용했고이 하위 클래스를 생각 해냈다.
// 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에서 테스트되었습니다.
위의 방법 중 어느 것도 도움이되지 않은 경우를 대비하여이 문제가 있었으며 문제는 다음 코드가 있다는 것입니다 ..
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
이 reloadData () 줄을 주석 처리하면 문제가 해결되었습니다. 이 줄이 필요하지 않았기 때문에 왜 추가했는지 모르겠습니다!
이 솔루션이 다른 사람에게 도움이되기를 바랍니다.
AutoLayout
그렇지 않으면 해당 xib에 대한 옵션을 해제하십시오 .
'IT Share you' 카테고리의 다른 글
apache가 localhost 외부에서 들어오는 연결을 수락하지 않습니다. (0) | 2020.12.14 |
---|---|
다른 머신에서 복사 한 스냅 샷 (rdb 파일)에서 redis 데이터를 복구하는 방법은 무엇입니까? (0) | 2020.12.14 |
IE11에서 createObjectURL로 만든 링크 열기 (0) | 2020.12.14 |
드롭 다운 목록에 값이 있는지 확인하는 가장 좋은 방법은 무엇입니까? (0) | 2020.12.14 |
MySQLi 준비된 문 오류보고 (0) | 2020.12.14 |