【问题标题】:UIScrollView or UICollectionView to swipe through images in order called from firebase?UIScrollView 或 UICollectionView 按从 firebase 调用的顺序滑动图像?
【发布时间】:2019-07-25 20:27:14
【问题描述】:

我的应用有一项功能,您可以在其中回答有关您关注的人的问题,例如(选项 A、B、C、D 是用户名称所在的位置):

这个想法是你回答一个关于用户的问题,它会从你在 firebase 数据库中关注的人中随机排列。图片是用户在注册时上传的个人资料图片,按照问题答案的左上角、右上角、左下角、右下角的顺序显示。

我正在尝试使用 UIScrollView,但所有图像都堆叠在一起,而不是能够在它们之间滑动(并且问题标签已经消失)

有没有办法让 ScrollView 工作,或者有没有更好/更有效的方法来集成 UICollectionView(我已经看到一些帖子推荐了类似的东西)?

我是新手,如果有任何帮助,我将不胜感激,在此先感谢 :)


更新:

我已经编辑了约束,因此图像视图的左右锚点应该是正确的,并在情节提要的 UIScrollView 顶部添加了一个 UIView。我还看到它可以用 UIPageViewController 来完成?

@IBOutlet weak var userImageScrollView: UIScrollView!
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var optionA: UIButton!
@IBOutlet weak var optionB: UIButton!
@IBOutlet weak var optionC: UIButton!
@IBOutlet weak var optionD: UIButton!

func setupLayout() {
    userImageScrollView.isPagingEnabled = true
    userImageScrollView.isScrollEnabled = true

    userImageScrollView.addSubview(imageViewA)
    imageViewA.translatesAutoresizingMaskIntoConstraints = false
    imageViewA.widthAnchor.constraint(equalTo: userImageScrollView.widthAnchor).isActive = true
    imageViewA.heightAnchor.constraint(equalTo: userImageScrollView.heightAnchor).isActive = true
    imageViewA.topAnchor.constraint(equalTo: userImageScrollView.topAnchor).isActive = true
    imageViewA.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true
    imageViewA.leftAnchor.constraint(equalTo: userImageScrollView.leftAnchor)
    imageViewA.rightAnchor.constraint(equalTo: imageViewB.leftAnchor)
    imageViewA.contentMode = .scaleAspectFit

    userImageScrollView.addSubview(imageViewB)
    imageViewB.translatesAutoresizingMaskIntoConstraints = false
    imageViewB.widthAnchor.constraint(equalTo: userImageScrollView.widthAnchor).isActive = true
    imageViewB.heightAnchor.constraint(equalTo: userImageScrollView.heightAnchor).isActive = true
    imageViewB.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true
    imageViewB.leftAnchor.constraint(equalTo: imageViewA.rightAnchor)
    imageViewA.rightAnchor.constraint(equalTo: imageViewC.leftAnchor)
    imageViewB.contentMode = .scaleAspectFit

    userImageScrollView.addSubview(imageViewC)
    imageViewC.translatesAutoresizingMaskIntoConstraints = false
    imageViewC.widthAnchor.constraint(equalTo: userImageScrollView.widthAnchor).isActive = true
    imageViewC.heightAnchor.constraint(equalTo: userImageScrollView.heightAnchor).isActive = true
    imageViewC.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true
    imageViewC.leftAnchor.constraint(equalTo: imageViewB.rightAnchor)
    imageViewC.rightAnchor.constraint(equalTo: imageViewD.leftAnchor)
    imageViewC.contentMode = .scaleAspectFit

    userImageScrollView.addSubview(imageViewD)
    imageViewD.translatesAutoresizingMaskIntoConstraints = false
    imageViewD.widthAnchor.constraint(equalTo: userImageScrollView.widthAnchor).isActive = true
    imageViewD.heightAnchor.constraint(equalTo: userImageScrollView.heightAnchor).isActive = true
    imageViewD.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true
    imageViewD.leftAnchor.constraint(equalTo: imageViewC.rightAnchor)
    imageViewD.rightAnchor.constraint(equalTo: userImageScrollView.rightAnchor)
    imageViewD.contentMode = .scaleAspectFit

    self.userImageScrollView.delegate = self
}

【问题讨论】:

  • 是的,您可以为此使用 UICollectionView。它允许您拥有 n 个图像
  • 我将如何使用 UICollectionView?由于我只想显示用户的 4 张个人资料图片(每个问题都不再显示),所以 UIScrollView 不能吗?
  • UIScrollView 可以,但 UICollectionView 更容易
  • 您好!它们在您的示例中堆叠的原因是因为您有 imageViewC.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true 而不是 imageViewC.topAnchor.constraint(equalTo: imageViewB.bottomAnchor).isActive = true

标签: ios swift uiscrollview uicollectionview firebase-storage


【解决方案1】:

您的 imageView 彼此重叠的原因是您定义的:

 imageViewB.leftAnchor.constraint(equalTo: imageViewA.leftAnchor)

这意味着:imageView B 的左侧与 imageViewA 的左侧相同,本质上是说它们的左侧都从同一位置开始,因此它们将在彼此之上。

所以你需要从左到右定义每一项:

imageViewB.leftAnchor.constraint(equalTo: imageViewA.rightAnchor)

imageViewBs 的左侧,从 imageViewA 的右侧开始。 imageView Cs leftAnchor 将等于 imageViewBs right 以此类推,直到您到达最终的 imageViewD,您需要让 leftAnchor 等于 imageViewCs rightAnchor 并且 imageViewDs rightAnchor 等于 scrollViews rightAnchor 以允许滚动正常工作。

如果您想向下滚动而不是从左到右滚动,而不是左右锚点,您也可以使用滚动视图轻松地做您想做的事情,使用centerXAnchors 将视图保持在滚动视图的中心

你需要想象你正在向某人描述布局,ImageViewA 在顶部,所以它的顶部锚点等于滚动视图的顶部锚点。

使用 imageViewB,您可以从上到下进行相同的描述,所以:

 imageViewB.topAnchor.constraint(equalTo: imageViewA.bottomAnchor).isActive = true

图像视图 B 的顶部从图像视图 A 的底部开始,然后您对其余部分执行相同操作,如下所示:

 imageViewC.topAnchor.constraint(equalTo: imageViewC.bottomAnchor).isActive = true

 imageViewD.topAnchor.constraint(equalTo: imageViewC.bottomAnchor).isActive = true

因为它是一个scrollView,并且你正在向下滚动,所以需要将顶部(imageViewA)设置为滚动视图的顶部,另外底部项需要将其bottomAnchor定义为滚动视图的底部,以便滚动以正常工作:

  imageViewD.bottomAnchor.constraint(equalTo: userImageScrollView.bottomAnchor).isActive = true 

您还在某些视图中同时使用centerXAnchorleftAnchor,想象centerXAnchorleftAnchor 相同,但只是从视图的不同部分描述它,就像您的centerXAnchor在leftAnchor之后,它只会使用centerX,这意味着图像将在scrollView中居中。

我建议遵循此模式并从头开始重新构建约束,真正关注需要定义的锚点和位置。您也可以使用 Interface Builder 来添加视图,但学习定义这样的约束将被证明是一项非常有价值的技能,并且有助于保持您的代码非常清晰和干净。

更新:

这段代码将完全按照您的意愿行事,记下滚动视图的高度和宽度以及我用来提供空间的常量。每个 imageView 都按照我上面所说的方式定义,从左到右,最后一项具有左右约束。删除你的 setupLayout 并用这个替换它(确保在必要时更改约束以适应你的应用程序):

 func setupLayout() {
    view.addSubview(scrollView)
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
    scrollView.heightAnchor.constraint(equalToConstant: 300).isActive = true
    scrollView.widthAnchor.constraint(equalToConstant: 300).isActive = true
    scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    scrollView.backgroundColor = .gray
    scrollView.isPagingEnabled = true

    scrollView.addSubview(imageViewA)
    imageViewA.translatesAutoresizingMaskIntoConstraints = false

    imageViewA.widthAnchor.constraint(equalToConstant: 250).isActive = true
    imageViewA.heightAnchor.constraint(equalToConstant: 250).isActive = true

    imageViewA.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 25).isActive = true
    imageViewA.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 25).isActive = true

    imageViewA.backgroundColor = .cyan

    scrollView.addSubview(imageViewB)
    imageViewB.translatesAutoresizingMaskIntoConstraints = false

    imageViewB.heightAnchor.constraint(equalToConstant: 250).isActive = true
    imageViewB.widthAnchor.constraint(equalToConstant: 250).isActive = true


    imageViewB.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 25).isActive = true
    imageViewB.leftAnchor.constraint(equalTo: imageViewA.rightAnchor, constant: 25).isActive = true

    imageViewB.backgroundColor = .red

    scrollView.addSubview(imageViewC)
    imageViewC.translatesAutoresizingMaskIntoConstraints = false

    imageViewC.heightAnchor.constraint(equalToConstant: 250).isActive = true
    imageViewC.widthAnchor.constraint(equalToConstant: 250).isActive = true


    imageViewC.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 25).isActive = true
    imageViewC.leftAnchor.constraint(equalTo: imageViewB.rightAnchor, constant: 25).isActive = true

    imageViewC.backgroundColor = .black

    scrollView.addSubview(imageViewD)
    imageViewD.translatesAutoresizingMaskIntoConstraints = false

    imageViewD.heightAnchor.constraint(equalToConstant: 250).isActive = true
    imageViewD.widthAnchor.constraint(equalToConstant: 250).isActive = true


    imageViewD.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 25).isActive = true
    imageViewD.leftAnchor.constraint(equalTo: imageViewC.rightAnchor, constant: 25).isActive = true
    imageViewD.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -25).isActive = true

    imageViewD.backgroundColor = .green


}

这是该代码的作用的 gif 图像:

via GIPHY

  • 别忘了在viewDidLoad()中拨打setupLayout

     override func viewDidLoad() {
    super.viewDidLoad()
    
    setupLayout()
    // Do any additional setup after loading the view, typically from a nib.
     }
    

【讨论】:

  • 嗨!我已经进行了这些更改,但它仍在堆叠 - 你认为这可能是因为最初,我没有在情节提要的 UIScrollView 顶部添加或连接 UIView - (我现在尝试添加它)。你认为我可以使 UIView 内容大小足够宽以适应 4 个图像视图在它们之间滚动吗? (我在代码中添加了更新以使其更易于查看:))
  • @edey 只是用 scrollView 测试了一些东西,只是看看我能不能让它完美。尝试添加scrollView.isPagingEnabled = true 我很快就会用完整代码更新我的答案到我的水平滚动 UIScrollView。
  • @edey 更新了问题,确保您花时间了解约束的工作原理并在我提供的 gif 中创建输出。例如,一些约束具有 25 和一些 -25 的常数,如果您仔细查看它们的位置和位置并检查 gif,您将看到什么意味着什么,它将帮助您更轻松地为您的设计实现它。祝你好运!
  • 哇!乐意效劳! :)
【解决方案2】:

是的,您可以将 CollectionView 与 pagingnation 一起使用。只需启用 CollecitonView 的分页选项。

1.在视图的顶部区域添加水平集合视图。启用分页选项 来自属性选择器。

  1. 将 CollectionView 单元格拖到 CollectionView 中。调整单元格以填充 整个 CollectionView
  2. 将图像添加到单元格

  3. 设置委托和数据源。

https://medium.com/@shaibalassiano/tutorial-horizontal-uicollectionview-with-paging-9421b479ee94

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    相关资源
    最近更新 更多