繁体   English   中英

如何在 UICollectionViewController 的标头中访问 UISegmentedControl?

[英]How can I access UISegmentedControl in header of UICollectionViewController?

所以这个问题相当简单。 我有一个UICollectionViewController (MyProfile.swift)具有报头部分(MyProfileHeader.swift) 在后者中,我有一个UISegmentedControl来返回collection view cells不同数量的项目和项目(我不想在UICollectionViewController初始化后者的类的UICollectionViewController )。 这是我的MyProfile.swift class代码。 我尝试在viewForSupplementaryElementOfKind方法中添加一个目标来返回不同的查询(有效),但我最终必须访问numberOfItemsInSectioncellForItemAtIndexPath方法中的分段控件。 所述"testObjects""writeObjects"array ,它们通过被查询值addTarget在该方法中viewForSupplementaryElementOfKind 我设置了indexPath但由于显而易见的原因它returns error ...如何访问分段控件?

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    var numberOfItems: Int? = 0

    let indexPath = NSIndexPath(forItem: 0, inSection: 0)

    let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "header", forIndexPath: indexPath) as! MyProfileHeader


    if header.userContent.selectedSegmentIndex == 1 {
        numberOfItems = textObjects.count
    } else if header.userContent.selectedSegmentIndex == 2 {
        numberOfItems = 0
    } else {
        numberOfItems = photoObjects.count
    }



    print("F: \(numberOfItems!)")
    return numberOfItems!
}

UICollectionReusableView创建一个UICollectionReusableView子类并将其命名为SegmentedHeader

-2nd 在SegmentedHeader类中添加一个协议来跟踪选择了哪个段。 当在 collectionView 的标头中选择一个段时,协议/委托将传递该段的值

-3rd 确保您设置了委托weak var delegate: SegmentedHeaderDelegate?

-4th 以编程方式创建segmentedControl添加一个名为selectedIndex(_ sender: UISegmentedControl) 的目标 当按下一个段时,您将该段的值传递给协议 trackSelectedIndex() 函数

protocol SegmentedHeaderDelegate: class {
    func trackSelectedIndex(_ theSelectedIndex: Int)
}

class SegmentedHeader: UICollectionReusableView {

    //MARK:- Programmatic Objects
    let segmentedControl: UISegmentedControl = {
        let segmentedControl = UISegmentedControl(items: ["Zero", "One", "Two"])
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        segmentedControl.tintColor = UIColor.red
        segmentedControl.backgroundColor = .white
        segmentedControl.isHighlighted = true
        segmentedControl.addTarget(self, action: #selector(selectedIndex(_:)), for: .valueChanged)
        return segmentedControl
    }()

    //MARK:- Class Property
    weak var delegate: SegmentedHeaderDelegate?

    //MARK:- Init Frame
    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .white
        setupAnchors()
    }

    //MARK:- TargetAction
    @objc func selectedIndex(_ sender: UISegmentedControl){

        let index = sender.selectedSegmentIndex

        switch index {

        case 0: // this means the first segment was chosen
            delegate?.trackSelectedIndex(0)
            break

        case 1: // this means the middle segment was chosen
            delegate?.trackSelectedIndex(1)
            break

        case 2: // this means the last segment was chosen
            delegate?.trackSelectedIndex(2)
            break

        default:
            break
        }
    }

    fileprivate func setupAnchors(){

        addSubview(segmentedControl)

        segmentedControl.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
        segmentedControl.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
        segmentedControl.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
        segmentedControl.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

在具有 UICollectionViewController 的类中:

重要 - 确保您在 viewForSupplementaryElementOfKind 中设置了委托,否则这些都不起作用

// MAKE SURE YOU INCLUDE THE SegmentedHeaderDelegate so the class conforms to it
class ViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, SegmentedHeaderDelegate{

// add a class property for the header identifier
let segmentedHeaderIdentifier = "segmentedHeader"

// add a class property to keep track of which segment was selected. This gets set inside the tracktSelectedIndex() function. You will need this for cellForRowAtIndexPath so you can show whatever needs to be shown for each segment
var selectedSegment: Int?

// register the SegmentedHeader with the collectionView
collectionView.register(SegmentedHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: segmentedHeaderIdentifier)

// inside the collectionView's delegate below add the header
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        var header: UICollectionReusableView?

        if kind == UICollectionElementKindSectionHeader{

            let segmentedHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: segmentedHeaderIdentifier, for: indexPath) as! SegmentedHeader

            // IMPORTANT >>>>MAKE SURE YOU SET THE DELEGATE or NONE OF THIS WILL WORK<<<<
            segmentedHeader.delegate = self

            // when the scene first appears there won't be any segments chosen so if you want a default one to show until the user picks one then set it here
            // for eg. when the scene first appears the last segment will show
            segmentedHeader.segmentedControl.selectedSegmentIndex = 2

            header = segmentedHeader
        }

        return header!
    }

// inside cellForRowAtIndexPath check the selectedSegmented class property to find out which segment was chosen
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TheCell, for: indexPath) as! TheCell

        // selectedSegment is the class property that gets set inside trackSelectedIndex()
        switch selectedSegment {

            case 0:
            // have the cell display something for the first segment
            break

            case 1:
            // have the cell display something for the middle segment
            break

            case 2:
            // have the cell display something for the last segment
            break

            default:
            break
        }

        return cell
}


// whenever a segment is selected, this delegate function  will get passed the segment's index. It runs a switch statement on theSelectedIndex argument/parameter. Based on that result it will set the selectedIndex class property to match the value from theSelectedIndex argument/parameter
func trackSelectedIndex(_ theSelectedIndex: Int) {

        switch theSelectedIndex {

        case 0: // this means the first segment was chosen
            // set the selectedSegment class property so you can use it inside cellForRowAtIndexPath
            selectedSegment = 0
            print("the selected segment is: \(theSelectedIndex)")
            break

        case 1: // this means the middle segment was chosen
            selectedSegment = 1
            print("the selected segment is: \(theSelectedIndex)")
            break

        case 2: // this means the last segment was chosen
            selectedSegment = 2
            print("the selected segment is: \(theSelectedIndex)")
            break

        default:
            break
        }
}

当在viewForSupplementaryElementOfKind为集合视图检索标头时,您可以在MyProfile存储对它的弱引用。

class MyProfile: UICollectionViewController {
...
...
weak var header: MyProfileHeader?
...    
...
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "header", forIndexPath: indexPath) as! MyProfileHeader

    return header
}

然后,您可以从UICollectionViewController任何其他函数访问它。

请注意,可以在viewForSupplementaryElementOfKind创建标头之前调用numberOfItemsInSectioncellForItemAtIndexPath ,因此当您在numberOfItemsInSectioncellForItemAtIndexPath或其他任何地方访问它时,您应该检查空值,然后假设分段控件处于默认值(因为它将是因为这是第一次显示视图)。 类似的东西

let selectedSegmentIndex = header?.userContent.selectedSegmentIndex ?? 0 //0 is the default value here

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM