簡體   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