提问者:小点点

当用户在swift中将屏幕从纵向转换为横向时,如何使scrollview内部的UIView适应屏幕方向


当用户在Swift中将屏幕从纵向转换为横向时,如何使scrollview内部的UIView适应屏幕方向?

var scrollView: UIScrollView = {
    var scroll = UIScrollView()
    scroll.translatesAutoresizingMaskIntoConstraints = false
      
    return scroll
}()

view.addSubview(scrollView)

scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
scrollView.heightAnchor.constraint(equalToConstant: 500).isActive = true

for i in 0..<arr.count {
    var contentView = UIView()
    contentView.frame = CGRect(x: i * Int(view.bounds.size.width) + 10, y: 0, width: Int(view.bounds.size.width) - 20 , height: Int(view.frame.height))

    scrollView.contentSize = CGSize(width: (view.frame.size.width * CGFloat((Double(i)+1))) ,height: scrollView.frame.size.height) 
}

图像


共2个答案

匿名用户

您真的希望使用自动布局,而不是尝试计算帧大小。让它为你做所有的工作。

根据您的代码,看起来您希望每个“ContentView”都是ScrollView框架的宽度减去20(因此每边都有10分的空间)。

通过将contentViews嵌入到UISTackView中,可以很容易地实现这一目标。

这里有一个简单的例子:

class ViewController: UIViewController {
    
    var scrollView: UIScrollView = {
        var scroll = UIScrollView()
        scroll.translatesAutoresizingMaskIntoConstraints = false
        
        return scroll
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        
        // use a stack view to hold and arrange the scrollView's subviews
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.spacing = 20

        // add the stackView to the scrollView
        scrollView.addSubview(stackView)

        // respect safe area
        let safeG = view.safeAreaLayoutGuide
        
        // use scrollView's Content Layout Guide to define scrollable content
        let layoutG = scrollView.contentLayoutGuide

        // use scrollView's Frame Layout Guide to define content height (since you want horizontal scrolling)
        let frameG = scrollView.frameLayoutGuide

        NSLayoutConstraint.activate([
            
            scrollView.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 100),
            
            // you're setting leading and trailing, so no need for centerX
            //scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0),
            
            scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 0),
            scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: 0),
            
            // let's constrain the scrollView bottom to the view (safe area) bottom
            //scrollView.heightAnchor.constraint(equalToConstant: 500),
            scrollView.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: -10.0),
            
            // constrain Top and Bottom of the stackView to scrollView's Content Layout Guide
            stackView.topAnchor.constraint(equalTo: layoutG.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: layoutG.bottomAnchor),
            
            // 10-pts space on leading and trailing
            stackView.leadingAnchor.constraint(equalTo: layoutG.leadingAnchor, constant: 10.0),
            stackView.trailingAnchor.constraint(equalTo: layoutG.trailingAnchor, constant: -10.0),
            
            // constrain stackView's height to scrollView's Frame Layout Guide height
            stackView.heightAnchor.constraint(equalTo: frameG.heightAnchor),
            
        ])
        
        // add some views to the stack view
        let arr: [UIColor] = [
            .red, .green, .blue, .yellow, .purple,
        ]
        
        for i in 0..<arr.count {
            let contentView = UIView()
            contentView.backgroundColor = arr[i]
            stackView.addArrangedSubview(contentView)
            
            // constrain each "contentView" width to scrollView's Frame Layout Guide width minus 20
            contentView.widthAnchor.constraint(equalTo: frameG.widthAnchor, constant: -20).isActive = true
            
            // don't do this
            //contentView.frame = CGRect(x: i * Int(view.bounds.size.width) + 10, y: 0, width: Int(view.bounds.size.width) - 20 , height: Int(view.frame.height))
            
            // don't do this
            //scrollView.contentSize = CGSize(width: (view.frame.size.width * CGFloat((Double(i)+1))) ,height: scrollView.frame.size.height)
            
        }

    }

}

看看这是不是你想要的。

匿名用户

您需要将您的子视图添加到滚动视图并设置它们的约束-使用自动布局。不要使用ContentView.Frame=CGRect(...)和ScrollView.ContentSize=CGSize(...)。

例如,您可以将for-in更改为:

注意:这只是一个示例,请根据您的需要更改您的for-in循环。

for i in 0..<arr.count {

    // we need to distinguish the first and last subviews (because different constraints)
    let topAnchor = i == 0 ? scrollView.topAnchor : scrollView.subviews.last!
    let isLast = i == arr.count - 1

    // here we will use a specific height for all subviews except the last one
    let subviewHeight = 60

    var contentView = UIView()
    contentView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(contentView)
    
    if isLast {
        NSLayoutConstraint.activate([
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor)
       ]
    } else {
        NSLayoutConstraint.activate([
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            contentView.heightAnchor.constraint(equalToConstant: subviewHeight),
            contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor)
       ]
    }
}