【问题标题】:Horizontal scroll UICollectionView showing tags (custom flow layout)水平滚动 UICollectionView 显示标签(自定义流布局)
【发布时间】:2016-10-02 09:29:41
【问题描述】:

我一直在尝试创建一个在两行中水平显示标签的集合视图。用户可以水平滚动以查看更多标签。与 Bandcamp 应用程序中的过滤器完全一样 https://itunes.apple.com/us/app/bandcamp/id706408639?mt=8

我找到了一个很好的教程,通过自定义 UICollectionViewFlowLayout 来做类似的事情。 https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/

但是,本教程适用于垂直集合视图,根据需要创建行。我需要的是标签向右流动,并将布局限制为两行。

这是教程中 UICollectionViewFlowLayout 的 sn-p

class FlowLayout: UICollectionViewFlowLayout {


  override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributesForElementsInRect = super.layoutAttributesForElementsInRect(rect)
    var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()

    var leftMargin: CGFloat = 0.0;

    for attributes in attributesForElementsInRect! {
        if (attributes.frame.origin.x == self.sectionInset.left) {
            leftMargin = self.sectionInset.left
        } else {
            var newLeftAlignedFrame = attributes.frame
            newLeftAlignedFrame.origin.x = leftMargin
            attributes.frame = newLeftAlignedFrame
        }
        leftMargin += attributes.frame.size.width + 8
        newAttributesForElementsInRect.append(attributes)
    }

    return newAttributesForElementsInRect
  }
}

谢谢!

【问题讨论】:

    标签: ios swift uicollectionview horizontal-scrolling uicollectionviewlayout


    【解决方案1】:

    所以,我终于设法为我的问题编写了一个解决方案:在 prepareLayout 上,我将 X/Y 位置重新分配给我的单元格,以及我的内容的宽度,然后我更新 LayoutAttributes 上的属性。诀窍是有一个包含两行信息的变量,并相应地更改每个单元格。这是遇到类似问题的人的代码

    import UIKit
    
    class FlowLayout: UICollectionViewFlowLayout {
    
    // SET SCROLL TO HORIZONTAL
    override init(){
        super.init()
        scrollDirection = .Horizontal
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        self.scrollDirection = .Horizontal
    }
    
    // SET VARIABLES: Content height/width and layout attributes
    private var contentWidth: CGFloat  = 0.0
    private var contentHeight: CGFloat  = 50.0
    private var cache = [UICollectionViewLayoutAttributes]()
    
    
    override func prepareLayout() {
        super.prepareLayout()
    
        // RUNS ONLY ONCE
        if cache.isEmpty {
            var row = 0
            let numberOfRows = 2
            var rowWidth = [CGFloat](count: numberOfRows, repeatedValue: 0)
            var xOffset = [CGFloat](count: numberOfRows, repeatedValue: 0)
    
            for item in 0 ..< collectionView!.numberOfItemsInSection(0) {
                let indexPath = NSIndexPath(forItem: item, inSection: 0)
                let tag = super.layoutAttributesForItemAtIndexPath(indexPath)
                let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
    
                attributes.frame = tag!.frame
                attributes.frame.origin.x = xOffset[row]
                cache.append(attributes)
    
                rowWidth[row] = rowWidth[row] + tag!.frame.size.width + 8
                xOffset[row] = xOffset[row] + tag!.frame.size.width + 8
                row = row >= (numberOfRows - 1) ? 0 : 1
            }
            contentWidth = rowWidth.maxElement()!
        }
    }
    
    // SETS DYNAMIC WIDTH BASED ON TAGS
    override func collectionViewContentSize() -> CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }
    
    // UPDATES CELL ATTRIBUTES
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var layoutAttributes = [UICollectionViewLayoutAttributes]()
        for attributes  in cache {
            if CGRectIntersectsRect(attributes.frame, rect ) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }
    
    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        return true
    }
    
    
    }
    

    【讨论】:

    【解决方案2】:

    将您的代码修改为右对齐

    class FlowLayout: UICollectionViewFlowLayout {
    
        override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            let attributesForElementsInRect = super.layoutAttributesForElementsInRect(rect)
            var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
    
            var rightMargin: CGFloat = rect.width;
    
            for attribute in attributesForElementsInRect! {
                attribute.frame.origin.x = rightMargin - attribute.frame.width - 8
    
                if attribute.frame.origin.x <= self.sectionInset.left {
                    rightMargin = rect.width - self.sectionInset.right
                    attribute.frame.origin.x = rightMargin - attribute.frame.width
                }
                rightMargin = rightMargin - attribute.frame.size.width - 8
                newAttributesForElementsInRect.append(attribute)
            }
    
            return newAttributesForElementsInRect
        }
    }
    

    【讨论】:

      【解决方案3】:

      我能够修改最初由Włodzimierz Woźniak 创建的代码库,这样我就可以在 UITableViewCell 中水平滚动标签标签。 UIScrollView 作为 UITableViewCell 中的子视图的编程添加几乎肯定可以为 UICollectionViewFlowLayout 实现。

      下面是代码工作原理的细分...

      1. 将字符串转换为标签
      2. 自定义标签
      3. 将标签转换为图像
      4. 将图像转换为属性文本
      5. 创建文本视图
      6. 将属性文本设置为 TextView
      7. 将 TextView 作为子视图添加到 ScollView
      8. 将 ScrollView 作为子视图添加到 TableViewCell

      你可以在这里找到一个可行的实现演示:

      https://github.com/austinmm/WordsAsTagLabels-Example

      【讨论】:

        猜你喜欢
        • 2013-10-18
        • 2016-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-12
        • 2016-01-25
        • 2021-02-06
        • 1970-01-01
        相关资源
        最近更新 更多