当前位置: 首页 > 知识库问答 >
问题:

Swift:以编程方式添加视图时,UIScrollView的可滚动内容大小不明确,不使用IB

慕晨
2023-03-14

我以编程方式创建视图,而不使用故事板。当打开调试视图层次结构时,我从Xcode收到了这个问题“运行时:布局问题:UIScrollView的可滚动内容大小不明确”。我认为这意味着对scollView的约束是不明确的。

我可以看到scrollView在视图层次结构中显示(黄色的),但它的子视图UIView没有显示。通过故事板/IB找到一些解决方案,尽管我无法将其与我的代码联系起来。感谢任何提示和建议。

下面是滚动视图的结构。

ScrollView
  ->UIView as contentView(coverImageContainer)
      -> UIImageView(coverArtImageView)
      -> UIButton
// scroller
    lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
//        scrollView.contentMode = .scaleToFill
        scrollView.contentInsetAdjustmentBehavior = .never
        scrollView.alwaysBounceVertical = true
        scrollView.backgroundColor = .yellow
        
        return scrollView
    }()
    
    // cover image
    lazy var coverImageContainer: UIView = {
        let containerView = UIView()
        containerView.translatesAutoresizingMaskIntoConstraints = false
        return containerView
    }()
    
    lazy var coverArtImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
        imageView.layer.cornerRadius = 5
        return imageView
    }()
    
    lazy var dismissChevron: UIButton = {
        let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.addTarget(self, action: #selector(disimissAction), for: .touchUpInside)
        return btn
    }()

override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .black
        backingImageView.image = backingImage
        
        view.addSubview(backingImageView)
        view.addSubview(dimmerLayer)
        view.addSubview(scrollView)
        scrollView.addSubview(coverImageContainer)
        scrollView.addSubview(stretchySkirt)
        coverImageContainer.addSubview(coverArtImageView)
        coverImageContainer.addSubview(dismissChevron)
        
        // set layout constraint
        configureLayout()
        ...        

    }
func configureLayout() {
        
        let g = view.safeAreaLayoutGuide
        backingImageleadInset = backingImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor)
        backingImageTrailingInset = backingImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor)
        backingImageTopInset = backingImageView.topAnchor.constraint(equalTo: view.topAnchor)
        backingImageBottomInset = backingImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        
        NSLayoutConstraint.activate([

            backingImageleadInset,
            backingImageTrailingInset,
            backingImageTopInset,
            backingImageBottomInset,
            
            dimmerLayer.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            dimmerLayer.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            dimmerLayer.topAnchor.constraint(equalTo: view.topAnchor),
            dimmerLayer.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: backingImageView.topAnchor, constant: 15),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            coverImageContainer.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
            coverImageContainer.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 57),
            coverImageContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            coverImageContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            coverImageContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -237),

            stretchySkirt.topAnchor.constraint(equalTo: coverImageContainer.bottomAnchor),
            stretchySkirt.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            stretchySkirt.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            stretchySkirt.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            coverArtImageView.centerXAnchor.constraint(equalTo: coverImageContainer.centerXAnchor),
            coverArtImageView.topAnchor.constraint(equalTo: coverImageContainer.topAnchor, constant: 38),
            coverArtImageView.leadingAnchor.constraint(equalTo: coverImageContainer.leadingAnchor, constant: 20),
            coverArtImageView.trailingAnchor.constraint(equalTo: coverImageContainer.trailingAnchor, constant: -20),
//            coverArtImageView.widthAnchor.constraint(equalToConstant: 354),
            coverArtImageView.heightAnchor.constraint(equalTo: coverArtImageView.widthAnchor),

            dismissChevron.centerXAnchor.constraint(equalTo: coverImageContainer.centerXAnchor),
            dismissChevron.topAnchor.constraint(equalTo: coverImageContainer.topAnchor, constant: 4),
        ])
    }

共有1个答案

王才
2023-03-14

正如东玛格的评论,我现在解决了这个问题。

我想实现的是如下图所示。这就像苹果音乐的最大卡视图。

好吧,问题出在< code>coverImageContainer的约束上,我应该约束它为view或view.safeAreaLayoutGuide而不是scrollView。因为我不希望< code>coverImageContainer滚动。

let g = view.safeAreaLayoutGuide 
NSLayoutConstraint.activate([
            . . . 
            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: backingImageView.topAnchor, constant: 15),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            coverImageContainer.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            coverImageContainer.topAnchor.constraint(equalTo: g.topAnchor, constant: 57),
            coverImageContainer.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            coverImageContainer.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            coverImageContainer.heightAnchor.constraint(equalTo: coverImageContainer.widthAnchor),

            stretchySkirt.topAnchor.constraint(equalTo: coverImageContainer.bottomAnchor),
            stretchySkirt.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            stretchySkirt.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            stretchySkirt.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            coverArtImageView.centerXAnchor.constraint(equalTo: coverImageContainer.centerXAnchor),
            coverArtImageView.topAnchor.constraint(equalTo: coverImageContainer.topAnchor, constant: 38),
            coverArtImageView.leadingAnchor.constraint(equalTo: coverImageContainer.leadingAnchor, constant: 38),
            coverArtImageView.heightAnchor.constraint(equalTo: coverArtImageView.widthAnchor),

            dismissChevron.centerXAnchor.constraint(equalTo: coverImageContainer.centerXAnchor),
            dismissChevron.topAnchor.constraint(equalTo: coverImageContainer.topAnchor, constant: 4),
        ])
 类似资料:
  • 各位开发人员,我在Interface Builder(Xcode5/iOS 7)中遇到了自动布局的问题。这是非常基本和重要的,所以我认为每个人都应该知道这是如何运作的。如果这是Xcode中的一个bug,那就是一个关键的bug! 因此,每当我有这样的视图层次结构时,我就会遇到麻烦: UIScrollView有坚实的约束,例如,每边50像素(没有问题)。然后我将顶部空间约束添加到UILabel(没问题

  • 我有: < li >应该可以在横向和纵向模式下工作的应用程序。 < li >在顶部显示全尺寸滚动视图。 < li >固定宽度和高度的滚动视图中的某些视图。(增加了H和W约束) < li >设置为在滚动视图中在容器中水平居中查看。(根据约束条件添加) 我知道解决这个问题的唯一方法是设置尾随和前导约束。但是对于不同的iPhone(5.5"、4.7"、4"),我需要设置不同的尾随和前导约束。 如何消除此

  • 问题内容: 如何滚动到代码底部?还是以更通用的方式,到子视图的任何一点? 问题答案: 您可以使用UIScrollView的功能滚动到内容视图的任何部分。假设您的scrollView是,这是一些滚动到底部的代码: 希望有帮助!

  • 我使用的是一个自定义视图,我添加了滚动条,如下所示: 现在有没有办法找出滚动条的像素厚度?对于垂直滚动条,我想找出宽度,对于水平滚动条,我想找出高度,两者都以像素为单位。 有没有办法通过编程实现这一点?

  • 下面的代码(在viewDidLoad中调用)导致一个完全红色的屏幕。我希望它是一个完全绿色的屏幕。为什么是红色的?我怎样才能让它变成绿色的呢?

  • 本文向大家介绍在iOS中以编程方式禁用滚动视图?,包括了在iOS中以编程方式禁用滚动视图?的使用技巧和注意事项,需要的朋友参考一下 滚动视图是iOS开发人员遇到的最困难和最复杂的主题之一。在这里,我们将看到如何以编程方式禁用滚动视图。 要禁用它,我们需要使滚动视图的“ isScrollEnabled”属性为false。 将以下代码复制到文件中。