如何使用按钮创建自定义集合视图?

Posted

技术标签:

【中文标题】如何使用按钮创建自定义集合视图?【英文标题】:How to create custom collection views with buttons? 【发布时间】:2017-06-19 23:42:31 【问题描述】:

我想创建一个集合视图,其中每个集合单元格都是可自定义的,并且每个单元格都有一个描述和一个按钮,每个单元格都应该指向另一个视图控制器,就像这样。

【问题讨论】:

那么是什么阻止您创建自定义单元格?到目前为止,您尝试过什么? 我只能用图像创建一个集合视图,但我真的不知道如何将它们转换为自定义按钮单元格 您是否尝试过将按钮拖入情节提要中的自定义单元格? 是的,但是当我在模拟器上运行应用程序时,单元格会随着文本、按钮和其中的图像一起消失,我也无法做到,所以情节提要中有多个单元格那些不容易看到的,可以水平滚动,就像上面的图片一样 UICollectionViewCells 可以通过实现 UICollectionViewDelegate 方法 didSelectItemAt: 表现得像按钮一样 【参考方案1】:

详情

xCode 8.3.2,斯威夫特 3.1

完整样本

CollectionViewCell

import UIKit

protocol CollectionViewCellDelegate: class 
    func touchUpInside(delegatedFrom cell: CollectionViewCell)


class CollectionViewCell: UICollectionViewCell 

    @IBOutlet weak var button: UIButton!
    weak var delegate: CollectionViewCellDelegate?

    @IBAction func touchUpInside(_ sender: UIButton) 
        delegate?.touchUpInside(delegatedFrom: self)
    

视图控制器

import UIKit

class ViewController: UIViewController 

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var collectionViewFlowLayout: UICollectionViewFlowLayout!

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        collectionView.dataSource = self
        collectionView.delegate = self
    

    override func viewWillLayoutSubviews() 
        super.viewWillLayoutSubviews()

        let inset:CGFloat = 20.0
        collectionViewFlowLayout.itemSize = collectionView.frame.size
        collectionViewFlowLayout.itemSize.width -= inset*2
        collectionViewFlowLayout.itemSize.height -= inset*2
        collectionViewFlowLayout.sectionInset.left = inset
        collectionViewFlowLayout.sectionInset.right = inset
    


extension ViewController: UICollectionViewDataSource 

    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return 1
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 10
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
        cell.delegate = self
        return cell
    


extension ViewController: UICollectionViewDelegate 

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
        print("Selected cell: \(indexPath)")
    



extension ViewController: CollectionViewCellDelegate 

    func touchUpInside(delegatedFrom cell: CollectionViewCell) 
        if let indexPath = collectionView.indexPath(for: cell) 
            print("Button pressed in cell: \(indexPath)")
        
    

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="ios.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="***_44641545" customModuleProvider="target" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0"  />
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="H99-jD-EE5">
                                <rect key="frame" x="0.0" y="20"  />
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="47T-Wc-WqB">
                                    <size key="itemSize"  />
                                    <size key="headerReferenceSize"  />
                                    <size key="footerReferenceSize"  />
                                    <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
                                </collectionViewFlowLayout>
                                <cells>
                                    <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="CollectionViewCell" id="X5i-B5-0He" customClass="CollectionViewCell" customModule="***_44641545" customModuleProvider="target">
                                        <rect key="frame" x="0.0" y="18.5"  />
                                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                        <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
                                            <rect key="frame" x="0.0" y="0.0"  />
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ng9-IJ-srl">
                                                    <rect key="frame" x="152.5" y="560"  />
                                                    <state key="normal" title="Button">
                                                        <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                                    </state>
                                                    <connections>
                                                        <action selector="touchUpInside:" destination="X5i-B5-0He" eventType="touchUpInside" id="mNT-vz-F9c"/>
                                                    </connections>
                                                </button>
                                            </subviews>
                                        </view>
                                        <color key="backgroundColor" name="gridColor" catalog="System" colorSpace="catalog"/>
                                        <constraints>
                                            <constraint firstAttribute="bottomMargin" secondItem="ng9-IJ-srl" secondAttribute="bottom" constant="12" id="AGX-Ye-rNr"/>
                                            <constraint firstItem="ng9-IJ-srl" firstAttribute="centerX" secondItem="X5i-B5-0He" secondAttribute="centerX" id="sFI-KT-pyQ"/>
                                        </constraints>
                                        <connections>
                                            <outlet property="button" destination="ng9-IJ-srl" id="mnC-Ln-j2F"/>
                                        </connections>
                                    </collectionViewCell>
                                </cells>
                            </collectionView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="H99-jD-EE5" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="0hj-ig-J9f"/>
                            <constraint firstItem="H99-jD-EE5" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="NWe-0c-k9w"/>
                            <constraint firstItem="H99-jD-EE5" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="axO-mx-zBv"/>
                            <constraint firstAttribute="trailing" secondItem="H99-jD-EE5" secondAttribute="trailing" id="eP4-pi-EX2"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="collectionView" destination="H99-jD-EE5" id="Cje-QN-sIz"/>
                        <outlet property="collectionViewFlowLayout" destination="47T-Wc-WqB" id="qBp-S0-pyU"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="132" y="137.18140929535232"/>
        </scene>
    </scenes>
</document>

结果

【讨论】:

【参考方案2】:

对于可能在我之后阅读此内容的任何人,我找到了一种方法来使用 Vasily Bodnarchuk 提供的其他答案来创建按钮。

按照他所做的一切,除了 Main.storyboard 代码(我太困惑了,无法弄清楚如何实现它)我只是进入了我的 ViewController 并向 UIViewControllerCell 添加了一个按钮。

之后,我创建了一个从我的 UICollectionView 到下一个 ViewController 的 Segway 并给它一个标识符。

我调整了上面提供的代码,并在他的函数中添加了一个“if”语句来打印选定的单元格:

extension ViewController: UICollectionViewDelegate 
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 

        print("Selected cell: \(indexPath)")

        if indexPath == [0,0] 
            self.performSegue(withIdentifier: "toGridView", sender: self)
        
    

如果您在控制台中注意到,它会打印每个单元格的值,并且我使用 indexPath 设置为一个值来引用该单元格。在这段代码中,[0,0] 处的按钮(单元格)将在单击时转到下一个 ViewController。

您可以为所有按钮执行此操作!

我会附上屏幕截图,以防我的描述让你感到困惑。

【讨论】:

以上是关于如何使用按钮创建自定义集合视图?的主要内容,如果未能解决你的问题,请参考以下文章

单击自定义按钮时如何创建视图

如何在单独的自定义视图中为按钮创建操作

iOS - 实现自定义集合视图布局

以编程方式创建形状视图并在集合视图单元格上使用

iOS如何知道使用自定义委托按下哪个按钮CollectionView

如何在自定义 UITableViewCell 按钮和第二个视图之间创建一个 segue