代码之家  ›  专栏  ›  技术社区  ›  Yuma Technical Inc.

Swift-如何将一堆视图放入滚动视图

  •  0
  • Yuma Technical Inc.  · 技术社区  · 6 年前

    C 目前我有一个自定义视图(返回一个uistakview),其中包含许多视图(uilabel、uiimageview,…)。它在高度足够的设备上显示很好。

    (顺便说一句,都做完了 以编程方式 (第页)

    在小屏幕设备上,它将只显示整个视图的顶部。所以我的解决方案是把它放在uiscroll视图中。(这应该很简单——但这让我很伤心。)

    但这根本无法显示,我做错了什么/错过了什么?

    部分代码如下:

    override init(frame: CGRect)
    {
        super.init(frame: frame)
    
        imageFrame.addSubview(prodImage)
        NSLayoutConstraint.activate([
            prodImage.topAnchor.constraint(equalTo: imageFrame.topAnchor),
            prodImage.trailingAnchor.constraint(equalTo: imageFrame.trailingAnchor),
            prodImage.leadingAnchor.constraint(equalTo: imageFrame.leadingAnchor),
            prodImage.bottomAnchor.constraint(equalTo: imageFrame.bottomAnchor),
            ])
    
        imageView.addSubview(imageFrame)
        NSLayoutConstraint.activate([
            imageFrame.topAnchor.constraint(equalTo: imageView.topAnchor),
            imageFrame.trailingAnchor.constraint(equalTo: imageView.trailingAnchor),
            imageFrame.leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
            imageFrame.bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
            ])
    

    //更多视图…

        let stack = UIStackView(arrangedSubviews: [imageView, prodName, prodPrice])
        stack.axis = .vertical
        stack.spacing = (self.frame.height > 400) ? (self.frame.height > 800) ? 15 : 10 : 5
        stack.distribution = UIStackViewDistribution.fill
    
        self.addSubview(stack)
        NSLayoutConstraint.activate([
            stack.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            stack.topAnchor.constraint(equalTo: self.topAnchor),
    //      stack.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
            stack.widthAnchor.constraint(equalTo: self.widthAnchor),
            ])
    }
    

    为了进行修改,我替换了下面的诗节:

    //  self.addSubview(stack)
    //  NSLayoutConstraint.activate([
    //      stack.leadingAnchor.constraint(equalTo: self.leadingAnchor),
    //      stack.topAnchor.constraint(equalTo: self.topAnchor),
    ////        stack.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
    //      stack.widthAnchor.constraint(equalTo: self.widthAnchor),
    //      ])
        let scrollView = UIScrollView()
        //      scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(stack)
        NSLayoutConstraint.activate([
            stack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            stack.topAnchor.constraint(equalTo: scrollView.topAnchor),
            stack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -50),
            stack.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            ])
    
        self.addSubview(scrollView)
        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            scrollView.topAnchor.constraint(equalTo: self.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
            scrollView.widthAnchor.constraint(equalTo: self.widthAnchor),
            ])
    

    如您所见,我试图禁用滚动视图的自动约束以使其适合其父级…所有尝试都失败。

    如何使此滚动视图可见?

    1 回复  |  直到 6 年前
        1
  •  1
  •   user1046037    6 年前

    可能的错误:

    • 您正在将堆栈视图的前导/尾随设置为滚动视图。
    • 如果打印帧,您可能会理解宽度为零
      • 这是因为:

        • 无法根据滚动视图确定堆栈视图的宽度。
        • 滚动视图是一种特殊视图,因为它的内容可能比滚动视图大。
        • 因此,需要显式设置内容视图(堆栈视图)的宽度
          • 可能的修复1:。

            而不是基于 scrollView设置它(假定scrollView作为子视图添加到viewController的视图中)

            stack.leadinganchor.constraint(equalto:view.leadinganchor),然后
            stack.topanchor.constraint(等于:view.topanchor)
            

            可能的修复2:。

            您可以显式设置堆栈视图的宽度定位点

            示例:

            下面给出了一个简单的示例,说明如何将堆栈视图与滚动视图一起使用。

            您的大致想法是正确的。

            • 滚动视图具有堆栈视图
            • 堆栈视图有一些子视图
              • 屏幕截图:

                一般说明:

                • 滚动视图是特殊的,因为滚动视图的内容可以比滚动视图本身更宽、更高(允许滚动)。
                • 因此,内容的宽度和高度不应绑定到滚动视图
                • 内容的宽度和高度应设置为没有滚动视图可播放的任何部分
                  • 战略

                    • 正如您所指出的,我喜欢使用滚动视图和内容视图
                    • 将实际内容添加到堆栈视图并使堆栈视图增长
                    • 因此,只要堆栈视图对滚动视图的约束设置正确,事情就应该到位。
                      • 调试:.

                        • 始终在viewdidAppears中打印帧值,以查看内容是否符合您的期望
                          • 示例代码:

                            类viewController:uiviewController{
                            
                            让ScrollView=uiScrollView()。
                            让ContentView=uiStackView()。
                            
                            让redview=uiview()。
                            让greenview=uiview()。
                            让YellowView=uiView()。
                            
                            重写func viewdidload()。{
                            super.viewdidload()。
                            
                            设置滚动视图()
                            设置内容视图()
                            设置预览()
                            设置绿色视图()
                            设置黄色视图()
                            }
                            
                            覆盖func viewdid显示(u动画:bool){
                            超级视图显示(动画)
                            
                            打印(“Scroll View=\(ScrollView.Frame)”)
                            打印(“content view=\(contentview.frame)”)
                            打印(“Red View=\(RedView.Frame)”)
                            打印(“green view=\(greenview.frame)”)
                            打印(“黄色视图=\(yellow view.frame)”)
                            }
                            
                            private func setupScrollView()。{
                            
                            ScrollView.BackgroundColor=.DarkGray
                            
                            view.addSubview(滚动视图)
                            
                            scrollView.translatesAutoResizingMaskinToConstraints=false
                            
                            ScrollView.LeadingAnchor.Constraint(等于:View.LeadingAnchor).IsActive=true
                            scrollview.trailinganchor.constraint(等于:view.trailinganchor).isactive=true
                            ScrollView.TopAnchor.Constraint(等于:View.TopAnchor).IsActive=true
                            ScrollView.BottomAnchor.Constraint(等于:View.BottomAnchor).IsActive=true
                            }
                            
                            private func setupContentView()。{
                            
                            contentView.axis=.垂直
                            contentView.distribution=.fill
                            ContentView.Alignment=.Fill
                            
                            ScrollView.AddSubView(内容视图)
                            
                            contentView.translatesAutoResizingMaskinToConstraints=false
                            
                            //策略是:
                            //内容视图的前导/尾随锚定设置为查看控制器的视图
                            //内容视图的顶部/底部锚定设置为滚动视图
                            
                            contentView.leadingAnchor.constraint(等于:view.leadingAnchor).isActive=true
                            contentview.trailinganchor.constraint(等于:view.trailinganchor).isactive=true
                            contentview.topanchor.constraint(等于:scrollview.topanchor).isactive=true
                            contentView.bottomAnchor.constraint(等于:scrollView.bottomAnchor).isActive=true
                            }
                            
                            private func setupredview()。{
                            
                            redview.backgroundcolor=.red
                            
                            redview.heightanchor.constraint(equalToconstant:400).isactive=true
                            
                            contentview.addarrangedsubview(redview)
                            }
                            
                            private func setupgreenview()。{
                            
                            greenview.backgroundcolor=.green
                            
                            greenview.heightanchor.constraint(equalToconstant:400).isactive=true
                            
                            ContentView.AddArrangedSubView(绿色视图)
                            }
                            
                            专用func setupYellowView()。{
                            
                            YellowView.BackgroundColor=.Yellow
                            
                            YellowView.HeightAnchor.Constraint(EqualToConstant:400).IsActive=true
                            
                            ContentView.AddArrangedSubView(黄色视图)
                            }
                            }
                            
                            你知道宽度是零
                            

                          这是因为:

                          • 无法基于滚动视图确定堆栈视图的宽度。
                          • 滚动视图是一种特殊的视图,因为它的内容可以大于滚动视图。
                          • 因此,需要显式设置内容视图(堆栈视图)的宽度

                          可能的修复1:

                          而不是基于scrollView把它放在view(假设ScrollView作为子视图添加到ViewController的视图中)

                              stack.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                              stack.topAnchor.constraint(equalTo: view.topAnchor),
                          

                          可能的修复2:

                          您可以显式设置堆栈视图的宽度定位点

                          例子:

                          下面给出了一个简单的示例,说明如何将堆栈视图与滚动视图一起使用。

                          你的想法是正确的。

                          • 滚动视图具有堆栈视图
                          • 堆栈视图有一些子视图

                          屏幕截图:

                          ScreenShot of the code

                          一般说明:

                          • 滚动视图是特殊的,因为滚动视图的内容可以比滚动视图本身更宽、更高(允许滚动)
                          • 因此,内容的宽度和高度不应绑定到滚动视图
                          • 内容的宽度和高度应设置为没有滚动视图可播放的任何部分

                          战略

                          • 正如您所指出的,我喜欢使用滚动视图和内容视图
                          • 将实际内容添加到堆栈视图并使堆栈视图增长
                          • 因此,只要栈视图对滚动视图的约束设置正确,事情就应该到位。

                          调试:

                          • 始终在中打印帧值viewDidAppear看看事情是否符合你的期望

                          示例代码:

                          class ViewController: UIViewController {
                          
                              let scrollView  = UIScrollView()
                              let contentView = UIStackView()
                          
                              let redView     = UIView()
                              let greenView   = UIView()
                              let yellowView  = UIView()
                          
                              override func viewDidLoad() {
                                  super.viewDidLoad()
                          
                                  setupScrollView()
                                  setupContentView()
                                  setupRedView()
                                  setupGreenView()
                                  setupYellowView()
                              }
                          
                              override func viewDidAppear(_ animated: Bool) {
                                  super.viewDidAppear(animated)
                          
                                  print("scroll view  = \(scrollView.frame)")
                                  print("content view = \(contentView.frame)")
                                  print("red view     = \(redView.frame)")
                                  print("green view   = \(greenView.frame)")
                                  print("yellow view  = \(yellowView.frame)")
                              }
                          
                              private func setupScrollView() {
                          
                                  scrollView.backgroundColor = .darkGray
                          
                                  view.addSubview(scrollView)
                          
                                  scrollView.translatesAutoresizingMaskIntoConstraints = false
                          
                                  scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
                                  scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
                                  scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
                                  scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
                              }
                          
                              private func setupContentView() {
                          
                                  contentView.axis            = .vertical
                                  contentView.distribution    = .fill
                                  contentView.alignment       = .fill
                          
                                  scrollView.addSubview(contentView)
                          
                                  contentView.translatesAutoresizingMaskIntoConstraints = false
                          
                                  //Strategy is:
                                  //content view's leading / trailing anchors are set to view controller's view
                                  //content view's top / bottom anchors are set to scroll view
                          
                                  contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
                                  contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
                                  contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
                                  contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
                              }
                          
                              private func setupRedView() {
                          
                                  redView.backgroundColor = .red
                          
                                  redView.heightAnchor.constraint(equalToConstant: 400).isActive = true
                          
                                  contentView.addArrangedSubview(redView)
                              }
                          
                              private func setupGreenView() {
                          
                                  greenView.backgroundColor = .green
                          
                                  greenView.heightAnchor.constraint(equalToConstant: 400).isActive = true
                          
                                  contentView.addArrangedSubview(greenView)
                              }
                          
                              private func setupYellowView() {
                          
                                  yellowView.backgroundColor = .yellow
                          
                                  yellowView.heightAnchor.constraint(equalToConstant: 400).isActive = true
                          
                                  contentView.addArrangedSubview(yellowView)
                              }
                          }