Swift:ScrollView 不滚动(如何设置约束)?
Posted
技术标签:
【中文标题】Swift:ScrollView 不滚动(如何设置约束)?【英文标题】:Swift: ScrollView not scrolling (how to set the constraints)? 【发布时间】:2018-06-26 14:06:18 【问题描述】:我正在尝试在我的故事板中设置一个带有自动布局的滚动视图,并在代码中使用几个按钮填充它,但滚动视图不滚动,我不明白如何设置约束让滚动可用?
尤其是如何设置内容视图的约束(那是什么?)。
在情节提要中,滚动视图位于屏幕底部(距安全区域 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 个按钮,但不会更多,并且无法滚动。
怎样才能让滚动成为可能?
【问题讨论】:
【参考方案1】:原因在 itemCount 中,您将其设置为 itemCount + 2 将是 3 因为 itemCount 在 for 循环中为 1 所以,将其设置为等于数组大小
filterScrollView.contentSize = CGSize(width: buttonWidth * CIFilterNames.count , height: yCoord)
【讨论】:
【参考方案2】:使用自动布局而不是计算尺寸会更好 - 为未来的更改提供更大的灵活性。
这是一个可以在 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
【讨论】:
以上是关于Swift:ScrollView 不滚动(如何设置约束)?的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 如何对 ScrollView 中的项目使用自动布局?
Swift iOS以编程方式在导航栏下方设置scrollView约束
Swift - ScrollView 中的 StackView 不滚动