IT TIP

UIScrollView contentSize가 작동하지 않습니다.

itqueen 2020. 12. 27. 20:33
반응형

UIScrollView contentSize가 작동하지 않습니다.


나는 UIScrollView펜촉에을 넣고 속성에 view연결했습니다 IBOutlet.

이제 내 viewDidLoad방법으로 이것을 할 때 다음과 같은 영향을 미치지 않는 것 같습니다 contentSize.

self.sv.backgroundColor = [UIColor yellowColor]; // this works
CGSize size =  CGSizeMake(1000.0, 1000.0); 
[self.sv setContentSize:size]; // this does not

(가)처럼 동작은 contentSize상기 프레임과 동일하다. 무슨 일이야? 이것은 AutoLayout을 끌 때 작동하기 시작했습니다. 왜?


나는 같은 문제가 있었다. 의 자동 레이아웃 UIScrollView이 엉망입니다.

주변에 일 다음에 넣어 모든 UIScrollView다른로 UIView, 그리고 넣어 UIView의 유일한 자식으로 UIScrollView. 그런 다음 자동 레이아웃을 사용할 수 있습니다.

끝 부분이 엉망인 경우 ( UIScrollView스크롤 방향의 끝 부분 ) 가능한 가장 낮은 우선 순위를 갖도록 끝 부분의 제약 조건을 변경하십시오.


scrollView의 contentSize를 업데이트하기 위해 viewWillLayoutSubviews를 시도했지만 저에게 효과적이었습니다.

- (void)viewDidLayoutSubviews
{
  [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
}

애플 문서

-(void)viewDidLayoutSubviews

뷰 컨트롤러에 뷰가 하위 뷰를 배치했음을 알리기 위해 호출됩니다.

토론

뷰 컨트롤러의 뷰에 대한 경계가 변경되면 뷰는 하위 뷰의 위치를 ​​조정 한 다음 시스템이이 메서드를 호출합니다. 그러나이 메서드가 호출 되어도 뷰의 하위 뷰의 개별 레이아웃이 조정되었음을 나타내는 것은 아닙니다. 각 하위보기는 자체 레이아웃을 조정해야합니다.

뷰 컨트롤러는이 메서드를 재정 의하여 뷰가 하위 뷰를 레이아웃 한 후 변경할 수 있습니다. 이 메서드의 기본 구현은 아무 작업도 수행하지 않습니다.


가장 쉽고 깔끔한 방법은 viewDidAppear에서 contentSize를 설정하여 자동 레이아웃의 효과를 무효화하는 것입니다. 이것은 임의의 뷰를 추가하는 것을 포함하지 않습니다. 그러나 구현이 작동하기 위해로드 순서에 의존하는 것은 최선의 방법이 아닐 수 있습니다.


여기에는 두 가지 문제가 있습니다. (1) viewDidLoad가 너무 빠릅니다. 레이아웃이 완료 될 때까지 기다려야합니다. (2) nib에서 오는 scrollview와 함께 autolayout을 사용하려면 제약 조건을 사용하여 크기를 완전히 설명해야합니다 contentSize(그런 다음 contentSize코드에서 전혀 설정하지 않음 ). 당신이해야 코드에서 설정하려는 방지 을 지시에서있는 ScrollView의 파단에 대한 제약을 contentSize. 후자를하고 싶은 것 같습니다. 이를 위해서는 scrollview의 유일한 최상위 하위 뷰 역할을하는 UIView가 필요하며 코드에서 자동 레이아웃을 사용 하지 않도록 설정 autoresizingMask하여 다른 외부 제약 조건을 활성화 하고 제거해야합니다. 이를 수행하는 방법의 예를 여기에 보여줍니다.

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m

그러나 또한 쇼 방법, 완전히 제약을 사용할 다음 예, 알 대신 의를 contentSize.


Interface Builder 내에서 UIScrollViews와 함께 AutoLayout을 사용하는 아주 쉬운 방법 :

1 단계 : 만들기UIScrollView

2 단계 : 다음 UIView과 같이 스크롤보기의 하위 항목을 만듭니다 .

-UIScrollView
---UIView
-----Your other content

(우리는 이것을라고 부를 것입니다 contentView).

3 단계 : 크기 검사기에서이보기에 높이와 너비 (예 : 320x700)를 지정합니다.

4 단계 (AutoLayout 사용) :contentView 수퍼 뷰 (the UIScrollView) 까지 명확한 제약 조건을 만듭니다 . 4 개의 가장자리 (상단, 선행, 후행, 하단)를 연결 한 다음 스크롤하려는 정의 된 너비와 높이를 지정합니다.

예 : 스크롤보기가 전체 화면에 걸쳐있는 경우 콘텐츠보기에 [기기 너비] 너비와 600 높이를 지정할 수 있습니다. 그런 다음의 콘텐츠 크기 UIScrollView를 일치하도록 설정합니다 .

또는:

4 단계 (AutoLayout 사용 안 함) : IB를 사용하여 이러한 새 컨트롤을 모두 뷰 컨트롤러에 연결합니다 (각 컨트롤에서 뷰 컨트롤러의 .h @implementation으로 Ctrl + 드래그). 각각이 각각 scrollView이라고 가정 해 봅시다 contentView. 다음과 같이 표시되어야합니다.

@interface YourViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, nonatomic) IBOutlet UIView *contentView;

@end

5 단계 (AutoLayout 사용 안 함) : 뷰 컨트롤러의 .h 파일에서 다음 메서드를 추가 (실제로 재정의)합니다.

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

이 코드를 사용하십시오. ScrollView setContentSize는 주 스레드에서 비동기로 호출되어야합니다.

빠른:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    DispatchQueue.main.async {
        var contentRect = CGRect.zero

        for view in self.scrollView.subviews {
           contentRect = contentRect.union(view.frame)
        }

        self.scrollView.contentSize = contentRect.size
    }
}

목표 C :

 - (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];

     dispatch_async(dispatch_get_main_queue(), ^ {
                        CGRect contentRect = CGRectZero;

                        for(UIView *view in scrollView.subviews)
                           contentRect = CGRectUnion(contentRect,view.frame);

                           scrollView.contentSize = contentRect.size;
                       });
}

이 코드 줄을 * .m 파일에 사용할 수 있습니다.

- (void)viewDidLoad{
   [scroll setContentSize:CGSizeMake(320, 800)]   ;
   [scroll setScrollEnabled:TRUE];
   [scroll setShowsVerticalScrollIndicator:NO];
   [scroll setShowsHorizontalScrollIndicator:YES];
}    

이를 위해 UIScrollView의 IBOutlet 속성을 * .h 파일로 가져와야합니다.

IBOutlet UIScrollView *scroll;

그리고 이것을 Storyboard에서 연결합니다.

또는,

이 방법을 * .m 파일에 사용할 수 있습니다.

-(void)viewDidLayoutSubviews 
{
  [scroll setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
   // this will pick height automatically from device's height and multiply it with 1.5  
}

이 두 솔루션은 xcode-5, xcode-6, xcode-6.1, xcode-6.2 에서 나를 위해 작동합니다.


contentSize를 설정하는 viewDidAppear것이 중요합니다.

하지만 3.5 인치 화면과 4 인치 화면에서 작동하는 변형도있었습니다. 4 인치 화면은 작동했지만 오래된 화면은 작동하지 않습니다. 두 iOS 7. Bizarre는 과소 평가입니다!


필자의 경우 뷰 컨트롤러의 수명주기를 사용할 수 없었기 때문에 마침내이 문제에 대한 자체 해결책을 찾았습니다. 고유 한 스크롤 뷰 하위 클래스를 만들고 UIScrollView 대신 사용합니다. 이것은 컬렉션 뷰 셀 내부의 스크롤 뷰에서도 작동했습니다.

 class MyScrollView:UIScrollView {

    var myContentSize:CGSize = CGSize.zero  // you must set this yourself 

    override func layoutSubviews() {
       super.layoutSubviews()
       contentSize = myContentSize
    }

 }

MyScrollView는 90이라는 태그로 펜촉에 정의되었습니다. 그렇다면 이것은 부모보기의 코드에서 콘텐츠 크기를 설정하는 좋은 방법입니다.

let scrollView = viewWithTag(90) as! MyScrollView      
scrollView.myContentSize = ...

제약 조건에 따라 자동 레이아웃을 얻을 수 없었습니다. 내 뷰는 이미 하위 클래스 UIScrollView 였기 때문에 setContentView :를 재정의하고 자동 레이아웃 0 높이 setContentSize : 메시지를 무시하여 문제를 해결했습니다.

@interface MyView : UIScrollView {}
@end

@implementation MyView
- (void)setContentSize:(CGSize)aSize {
    if (aSize.height > 0)
        [super setContentSize:aSize];
}
@end

uiscrollview 및 uiview가 작동하도록하는 방법을 단계별로 단계별로 시청할 때까지 프로그래밍 방식으로 uiscrollview를 설정했습니다. https://www.youtube.com/watch?v=PgeNPRBrB18

비디오를보고 나면 Interface Builder를 좋아하게 될 것입니다.

투표


of a AutoLayout를 설정하는 정말 쉬운 방법을 사용 하는 경우 다음과 같이 추가하면됩니다.contentSizeUIScrollView

CGFloat contentWidth = YOUR_CONTENT_WIDTH;

NSLayoutConstraint *constraintWidth = 
 [NSLayoutConstraint constraintWithItem:self.scrollView 
                              attribute:NSLayoutAttributeTrailing 
                              relatedBy:NSLayoutRelationEqual 
                                 toItem:self.scrollView 
                              attribute:NSLayoutAttributeLeading 
                             multiplier:1 
                               constant:contentWidth];

[self.scrollView addConstraint:constraintWidth];

레이블의 동적 높이가보기 높이를 초과하면 여전히 스크롤되지 않습니다.

위의 올바른 것으로 표시된 yuf의 답변을 수행했습니다 (스크롤 뷰에 콘텐츠 뷰를 추가하고 콘텐츠 뷰에서 스크롤 뷰로의 선행, 후행, 상단 하단 및 동일한 너비의 제약 조건을 설정했습니다). 내부 컨트롤 높이가 스크롤 뷰의 높이를 초과하면 스크롤되지 않습니다.

여기에 이미지 설명 입력

내 콘텐츠보기 안에는 이미지와 그 아래에 3 개의 레이블이 있습니다. 각 레이블은 텍스트 양에 따라 자체 높이를 조정합니다 (이를 위해 단어 줄 바꿈 및 numberoflines = 0으로 설정 됨).

내가 가진 문제는 내 콘텐츠보기의 높이가 스크롤보기 / 기본보기의 높이를 초과했을 때 레이블의 동적 높이로 조정되지 않는다는 것입니다.

이 문제를 해결하기 위해 하단 레이블과 contentview 사이 Bottom Space to Container 제약 조건 을 설정하고 값을 40으로 지정해야한다고 말했습니다. 이것은 이제 내 contentview가 마지막 레이블의 하단과 자체 사이에 공간이 있고 완벽하게 스크롤 되도록 높이를 조정한다는 것을 의미합니다 !

예이!


...이 밖으로 시도
당신이처럼 모든 제약 조건을 추가 UIView (스토리 보드 내 ViewControler의 스크린 샷 참조 ) 지금 트릭을 시작합니다. 마지막 개체를 선택하고 아래쪽 제약 조건을 선택합니다. (위의 screenShot, Instagram 버튼의 Bottom Constraint (노란색 선) 참조) 아래 스크린 샷과 같이 Size Inspector에서 상수를 변경합니다.
여기에 이미지 설명 입력

여기에 이미지 설명 입력

Constant = 8이 필요하지만 요구 사항에 따라 변경할 수 있습니다. 이 상수는 주황색 버튼의 하단과 scrollView 사이의 공간입니다.

편집하다

뷰의 계층 구조를 확인하십시오.

0) ViewController.view ( 선택 사항 )
1) UIScrollView
2) UIView ( "contentView"로 이름 변경)
3) UIView (이보기는 scrollView 스크롤 을 만들 콘텐츠입니다 )


I got Autolayout to work for paginated scroll views whose pages occupy the full-width of the screen. The pages automatically resize according to the scroll view's size. I haven't tested this for lesser-width scroll views but do comment away if it works--I beleieve it should. Targeted for iOS 9, wrote code in Swift 2, used a mix of IB's and custom code in awakeFromNib.

Steps:

  • Define a full-screen scroll view.
  • Inside the scroll view, add a UIView (I called mine contentView) whose top, trailing, bottom, and leading edges to the scroll view are all zero; the height is equal to the scroll view's; but the width is the scroll view's width times the number of pages. If you're doing this visually, you will see your content view extend beyond your scroll view in Inteface Builder.
  • For every "page" inside the contentView, add Autolayout rules to put them side-by-side each other, but most importantly, give them each a constraint so that their widths are equal to the scroll view's, not the content view's.

아래 샘플 코드. embedChildViewController하위 VC를 추가하는 편리한 방법입니다 setupLayoutRulesForPages.. 정확히 두 페이지가 있으므로 기능이 너무 간단하지만 필요에 따라 확장 할 수 있습니다.

내 뷰 컨트롤러에서 :

override func loadView() {
    self.view = self.customView
}

override func viewDidLoad() {
super.viewDidLoad()

self.embedChildViewController(self.addExpenseVC, toView: self.customView.contentView, fillSuperview: false)
self.embedChildViewController(self.addCategoryVC, toView: self.customView.contentView, fillSuperview: false)
self.customView.setupLayoutRulesForPages(self.addExpenseVC.view, secondPage: self.addCategoryVC.view)
}

내 사용자 정의보기 :

class __AMVCView: UIView {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!

    override func awakeFromNib() {
        super.awakeFromNib()

        self.scrollView.pagingEnabled = true
        self.scrollView.bounces = true
        self.scrollView.showsHorizontalScrollIndicator = false
        self.scrollView.showsVerticalScrollIndicator = false

        self.pageControl.numberOfPages = 2

        self.contentView.backgroundColor = UIColor.blueColor()
        self.scrollView.backgroundColor = UIColor.clearColor()
        self.backgroundColor = UIColor.blackColor()
    }

    func setupLayoutRulesForPages(firstPage: UIView, secondPage: UIView) {
        guard self.contentView.subviews.contains(firstPage) && self.contentView.subviews.contains(secondPage)
            else {
                return
        }

        let rules = [
            "H:|-0-[firstPage]-0-[secondPage]-0-|",
            "V:|-0-[firstPage]-0-|",
            "V:|-0-[secondPage]-0-|"
        ]
        let views = [
            "firstPage" : firstPage,
            "secondPage" : secondPage
        ]
        let constraints = NSLayoutConstraint.constraintsWithVisualFormatArray(rules, metrics: nil, views: views)

        UIView.disableAutoresizingMasksInViews(firstPage, secondPage)
        self.addConstraints(constraints)

        // Add the width Autolayout rules to the pages.
        let widthConstraint = NSLayoutConstraint(item: firstPage, attribute: .Width, relatedBy: .Equal, toItem: self.scrollView, attribute: .Width, multiplier: 1, constant: 0)
        self.addConstraint(widthConstraint)
    }

}

참조 URL : https://stackoverflow.com/questions/12846351/uiscrollview-contentsize-not-working

반응형