簡體   English   中英

如何在快速按下集合視圖單元格時修復自定義視圖中的約束

[英]How to fix constraints in custom view when collection view cell pressed in swift

我有一個測試應用程序,我第一次嘗試以編程方式創建 100%。 我有一個簡單的 collectionView,每個單元格中有一個圖像和一個標簽。

在此處輸入圖片說明

當我按下單元格時,會彈出一個自定義視圖,其中包含兩個視圖,紅色和藍色,將來會有內容,但現在只有兩個視圖。

在此處輸入圖片說明

我想讓該應用程序在縱向和橫向模式下都能正常工作,而且一開始它運行良好。 我第一次按下單元格時,彈出視圖適用於縱向和橫向。 在此處輸入圖片說明

這就是我想要在按下單元格時發生的情況,但是當我單擊視圖以使其消失時出現問題,然后按下任何單元格:

在此處輸入圖片說明

第一個方向,無論是橫向還是縱向,都很好,但是當我現在改變方向時出現問題,按下第二個或更多單元格。

在此處輸入圖片說明

我嘗試使用首次亮相的視圖層次結構,這就是錯誤屏幕的樣子。

在此處輸入圖片說明

我遵循的主要思想是本網站的教程: https : //iosrevisited.blogspot.com/2017/10/adaptive-autolayout-programmatically-iphone-x.html

我能夠完成本教程,並且效果很好。 我的不同之處在於,我的視圖應該在用戶需要時出現和消失。

這是具有 collectionView 的視圖控制器的代碼:

import UIKit

extension ViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 150)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    }
}


extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! TestingCollectionViewCell
        cell.backgroundColor = .white
        let img = UIImage(named: self.items[indexPath.row])
        cell.imageView.image = img
        cell.imageName.text = "\(self.items[indexPath.row])"
        return cell
    }


    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("\(items[indexPath.row])")
        self.presentInfoView(withInfo: items[indexPath.row])
    }
}

class ViewController: UIViewController, BlurDelegate {

    func removeBlurView() {
        for subview in view.subviews {
            if subview.isKind(of: UIVisualEffectView.self) {
                subview.removeFromSuperview()
                self.infoView.removeFromSuperview()
            }
        }
    }

    let infoView: InfoView = {
       let view = InfoView()
        view.layer.cornerRadius = 5
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    fileprivate var items: [String] = [
        "photo1",
        "photo2",
        "photo3",
        "photo4",
        "photo5",
        "photo6",
        "photo7",
        "photo8",
        "photo9",
        "photo10",
        "photo11",
        "photo12",
        "photo13",
        "photo14",
        "photo15",
        "photo16",
        "photo17",
        "photo18",
        "photo19",
        "photo20",
        "photo21",
        "photo22",
        "photo23",
        "photo24"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        let collection = UICollectionView(frame: view.frame, collectionViewLayout: UICollectionViewFlowLayout())
                //allows us to use auto layout constraints
        collection.translatesAutoresizingMaskIntoConstraints = false
        collection.backgroundColor = .black
        view.addSubview(collection)
        collection.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        collection.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        collection.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        collection.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true

        collection.dataSource = self
        collection.delegate = self

        collection.register(TestingCollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        self.navigationItem.title = "Testing"

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        var touch: UITouch? = touches.first
        if touch?.view != infoView {
            dismissView()

        }
    }


    func dismissView() {

        //dismiss(animated: true, completion: nil)
        removeBlurView()

    }

    func setBlurView() {
        let blurView = UIVisualEffectView()
        blurView.frame = view.frame
        blurView.effect = UIBlurEffect(style: .regular)
        blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(blurView)
    }

    func presentInfoView(withInfo info: String) {
        setBlurView()
        view.addSubview(infoView)
        infoView.addView()
        let img = UIImage(named: info)
        infoView.imageView.image = img
        infoView.nameLbl.text = info


        infoView.backgroundColor = .white
        infoView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        infoView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true
        //infoView.widthAnchor.constraint(equalToConstant: view.frame.width - 64).isActive = true
        infoView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.8).isActive = true
        //infoView.heightAnchor.constraint(equalToConstant: view.frame.height - 64).isActive = true
        infoView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -44).isActive = true
        infoView.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)

        infoView.alpha = 0

        UIView.animate(withDuration: 0.5) {
            self.infoView.alpha = 1
            self.infoView.transform = .identity
        }
    }

}

為了稍微清楚一點,我們想要的是讓模糊視圖隨着視圖的出現而出現和消失。

這是單元格出現時將出現的視圖的代碼:

import UIKit
protocol BlurDelegate: class {
    func removeBlurView()
}
class InfoView: UIView {


    let topView: UIView = {
       let view = UIView()
        view.backgroundColor = .blue
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    let btmView: UIView = {
       let view = UIView()
        view.backgroundColor = .red
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()


    var portraitConstraints: [NSLayoutConstraint] = []
    var landscapeConstraints: [NSLayoutConstraint] = []

    override init(frame: CGRect) {
        super.init(frame: frame)
        NotificationCenter.default.addObserver(self, selector: #selector(toggleConstraints), name: UIDevice.orientationDidChangeNotification, object: nil)
        //addView()
    }

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

    func addView() {
        let guide = self.safeAreaLayoutGuide

        //image layout
        self.addSubview(topView)
        let defaultImgTop = topView.topAnchor.constraint(equalTo: guide.topAnchor)
        let defaultImgLeading = topView.leadingAnchor.constraint(equalTo: guide.leadingAnchor)

        //portrait
        let portraitImgTrailing = topView.trailingAnchor.constraint(equalTo: guide.trailingAnchor)
        let portraitImgHeight = topView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.5)


        //lbl layouts
        self.addSubview(btmView)
        let defaultlblTrailing = btmView.trailingAnchor.constraint(equalTo: guide.trailingAnchor)
        let defaultLblBottom = btmView.bottomAnchor.constraint(equalTo: guide.bottomAnchor)

        //portrait
        let portraitLblBottom = btmView.topAnchor.constraint(equalTo: topView.bottomAnchor)
        let portraitLblLeading = btmView.leadingAnchor.constraint(equalTo: guide.leadingAnchor)

        //imageView landscape constraints
        let landscapeImgBottom = topView.bottomAnchor.constraint(equalTo: guide.bottomAnchor)
        let landscapeImgWidth = topView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.5)


        //label landscape constraints
        let landscapeLblTop = btmView.topAnchor.constraint(equalTo: guide.topAnchor)
        let landscapeLblLeading = btmView.leadingAnchor.constraint(equalTo: topView.trailingAnchor)

        let defaultConstriants = [defaultImgTop, defaultImgLeading, defaultLblBottom, defaultlblTrailing]
        portraitConstraints = [portraitImgHeight, portraitImgTrailing, portraitLblBottom, portraitLblLeading]
        landscapeConstraints = [landscapeImgBottom, landscapeLblTop, landscapeLblLeading, landscapeImgWidth]
        self.addConstraints(defaultConstriants)
        toggleConstraints()
    }



    @objc func toggleConstraints() {
        if UIDevice.current.orientation.isLandscape {
            self.removeConstraints(portraitConstraints)
            self.addConstraints(landscapeConstraints)
        } else {
            self.removeConstraints(landscapeConstraints)
            self.addConstraints(portraitConstraints)
        }
    }

}

我從上面添加的站點中獲得了這個視圖中的想法。 我不得不改變一些東西,因為它是一個視圖,但它應該是一樣的。 我認為錯誤就在於此,但我嘗試更改縱向和橫向的約束,但沒有奏效。 我試着把它寫下來,看看哪些約束被刪除,然后再次更新,但我似乎無法找到是哪一個讓我感到困惑。 我知道問題應該出在紅色視圖的頂部錨點或藍色視圖的底部錨點,但我無法弄清楚哪個是錯誤的或錯誤的。

我希望這是足夠的信息,但請詢問我是否還有其他需要幫助的地方。

另外,如果不是很麻煩,如果您注意到視圖出現時,導航欄似乎沒有模糊。 這使得自定義視圖看起來像是在頂部被切斷。 如果您知道一種模糊導航欄的方法,或者嘗試將視圖的頂部錨點向下推以使其看起來不那么糟糕,我們將不勝感激。

我試過用

self.navigationItem.bottomAnchor

我試圖在視圖中添加一個帶有常量的頂部錨點,但我上面的配置是我能找到的讓視圖每次都完美顯示的最佳方式。 非常感謝

presentInfoView 函數刪除 infoView.addView()

     override init(frame: CGRect) {
                super.init(frame: frame)
                NotificationCenter.default.addObserver(self, selector: #selector(toggleConstraints), name: UIDevice.orientationDidChangeNotification, object: nil)
                addView()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM