Swift: ScrollView не прокручивается (как установить ограничения)?

Я пытаюсь настроить представление прокрутки с автоматическим макетом в своей раскадровке и заполнить его парой кнопок в коде, но представление прокрутки не прокручивается, и я не понимаю, как настроить ограничения, чтобы сделать прокрутку доступной ?

Особенно, как установить ограничения на просмотр содержимого (что это?).

В раскадровке вид прокрутки размещается внизу экрана (20 пикселей до безопасной зоны) и от ведущего к замыкающему. Он имеет размер 375x80.

Теперь в коде показано, как представление прокрутки заполняется кнопками и как оно настраивается:

override func viewDidLoad() {
    super.viewDidLoad()

    var xCoord: CGFloat = 5
    var yCoord: CGFloat = 5
    let buttonWidth: CGFloat = 70
    let buttonHeight: CGFloat = 70
    let gapBetweenButtons: CGFloat = 5

    var itemCount = 0

    for i in 0..<CIFilterNames.count {
        itemCount = 1

        // Button properties
        let filterButton = UIButton(type: .custom)
        filterButton.frame = CGRect(x: xCoord, y: yCoord, width: buttonWidth, height: buttonHeight)
        filterButton.tag = itemCount
        filterButton.addTarget(self, action: #selector(ViewController.filterButtonTapped(sender:)), for: .touchUpInside)
        filterButton.layer.cornerRadius = 6
        filterButton.clipsToBounds = true

        //Code for filters will be added here

        let ciContext = CIContext(options: nil)
        let coreImage = CIImage(image: originalImage.image!)
        let filter = CIFilter(name: "\(CIFilterNames[i])")
        filter!.setDefaults()
        filter?.setValue(coreImage, forKey: kCIInputImageKey)
        let filteredImageDate = filter!.value(forKey: kCIOutputImageKey) as! CIImage
        let filteredImageRef = ciContext.createCGImage(filteredImageDate, from: filteredImageDate.extent)
        let imageForButton = UIImage(cgImage: filteredImageRef!)

        // Asign filtered image to the button
        filterButton.setBackgroundImage(imageForButton, for: .normal)

        // Add buttons in the scrollView
        xCoord += buttonWidth + gapBetweenButtons
        filterScrollView.addSubview(filterButton)

    }

    filterScrollView.contentSize = CGSize(width: buttonWidth * CGFloat(itemCount + 2), height: yCoord)
    filterScrollView.isScrollEnabled = true


}

В зависимости от размера устройства отображаются 4 или 5 кнопок, но не более, и прокрутка невозможна.

Что можно сделать, чтобы прокрутка стала возможной?


person RjC    schedule 17.01.2018    source источник


Ответы (2)


Причина в itemCount, вы устанавливаете его на itemCount + 2, будет 3, поскольку itemCount равен 1 из цикла for, поэтому установите для него равный размер массива

   filterScrollView.contentSize = CGSize(width: buttonWidth * CIFilterNames.count  , height: yCoord)

введите здесь описание изображения

person Sh_Khan    schedule 17.01.2018

Вам будет намного лучше использовать автоматическое расположение, а не расчет размеров - это дает гораздо больше гибкости для будущих изменений.

Вот пример, который вы можете запустить на странице Playground. Я использовал «количество» в качестве меток кнопок, так как у меня нет ваших изображений. Если вы добавляете изображения, вы можете раскомментировать соответствующие строки и удалить строки .setTitle и .backgroundColor:

import UIKit
import PlaygroundSupport
import CoreImage

class TestViewController : UIViewController {

    var CIFilterNames = [
        "CIPhotoEffectChrome",
        "CIPhotoEffectFade",
        "CIPhotoEffectInstant",
        "CIPhotoEffectNoir",
        "CIPhotoEffectProcess",
        "CIPhotoEffectTonal",
        "CIPhotoEffectTransfer",
        "CISepiaTone"
    ]

    let buttonWidth: CGFloat = 70
    let buttonHeight: CGFloat = 70
    let gapBetweenButtons: CGFloat = 5

    override func viewDidLoad() {
        super.viewDidLoad()

        // create a UIScrollView
        let filterScrollView = UIScrollView()

        // we will set the auto-layout constraints
        filterScrollView.translatesAutoresizingMaskIntoConstraints = false

        // set background color so we can see the scrollView when the images are scrolled
        filterScrollView.backgroundColor = .orange

        // add the scrollView to the view
        view.addSubview(filterScrollView)

        // pin scrollView 20-pts from bottom/leading/trailing
        filterScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0).isActive = true
        filterScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20.0).isActive = true
        filterScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20.0).isActive = true

        // scrollView height is 80
        filterScrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true

        // create a UIStackView
        let stackView = UIStackView()

        stackView.spacing = gapBetweenButtons

        // we will set the auto-layout constraints
        stackView.translatesAutoresizingMaskIntoConstraints = false

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

        // with auto-layout, scroll views use the content's constraints to
        // determine the contentSize,
        // so pin the stackView to top/bottom/leading/trailing of the scrollView
        // with padding to match the gapBetweenButtons
        stackView.leadingAnchor.constraint(equalTo: filterScrollView.leadingAnchor, constant: gapBetweenButtons).isActive = true
        stackView.topAnchor.constraint(equalTo: filterScrollView.topAnchor, constant: gapBetweenButtons).isActive = true
        stackView.trailingAnchor.constraint(equalTo: filterScrollView.trailingAnchor, constant: -gapBetweenButtons).isActive = true
        stackView.bottomAnchor.constraint(equalTo: filterScrollView.bottomAnchor, constant: -gapBetweenButtons).isActive = true

        // loop through the images
        for i in 0..<CIFilterNames.count {

            // create a new UIButton
            let filterButton = UIButton(type: .custom)
            filterButton.tag = i

            // we will set the auto-layout constraints, and allow the stackView
            // to handle the placement
            filterButton.translatesAutoresizingMaskIntoConstraints = false

            // set the width and height constraints
            filterButton.widthAnchor.constraint(equalToConstant: buttonWidth).isActive = true
            filterButton.heightAnchor.constraint(equalToConstant: buttonHeight).isActive = true

            filterButton.layer.cornerRadius = 6
            filterButton.clipsToBounds = true

            filterButton.addTarget(self, action: #selector(filterButtonTapped(_:)), for: .touchUpInside)

            // this example doesn't have your images, so
            // set button title and background color
            filterButton.setTitle("\(i)", for: .normal)
            filterButton.backgroundColor = .blue

//          //Code for filters will be added here
//          
//          let ciContext = CIContext(options: nil)
//          let coreImage = CIImage(image: originalImage.image!)
//          let filter = CIFilter(name: "\(CIFilterNames[i])")
//          filter!.setDefaults()
//          filter?.setValue(coreImage, forKey: kCIInputImageKey)
//          let filteredImageDate = filter!.value(forKey: kCIOutputImageKey) as! CIImage
//          let filteredImageRef = ciContext.createCGImage(filteredImageDate, from: filteredImageDate.extent)
//          let imageForButton = UIImage(cgImage: filteredImageRef!)
//          
//          // Asign filtered image to the button
//          filterButton.setBackgroundImage(imageForButton, for: .normal)


            // add the image view to the stackView
            stackView.addArrangedSubview(filterButton)

        }

    }

    func filterButtonTapped(_ sender: Any?) -> Void {
        if let b = sender as? UIButton {
            print("Tapped:", b.tag)
        }
    }

}

let vc = TestViewController()
vc.view.backgroundColor = .red
PlaygroundPage.current.liveView = vc
person DonMag    schedule 17.01.2018