简体   繁体   English

如何在快速按下集合视图单元格时修复自定义视图中的约束

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

I have a test app that I am trying to create 100% programmatically for the first time.我有一个测试应用程序,我第一次尝试以编程方式创建 100%。 I have a simple collectionView that has an image and a label in each cell.我有一个简单的 collectionView,每个单元格中有一个图像和一个标签。

在此处输入图片说明

When I press the cell, a custom view pops up with two views, red and blue, that in the future will have content, but for now it is just two views.当我按下单元格时,会弹出一个自定义视图,其中包含两个视图,红色和蓝色,将来会有内容,但现在只有两个视图。

在此处输入图片说明

I wanted to have the app work in both portrait and landscape orientation, and in the beginning it works well.我想让该应用程序在纵向和横向模式下都能正常工作,而且一开始它运行良好。 The first time I press the cell the pop up view works on both portrait and landscape orientation.我第一次按下单元格时,弹出视图适用于纵向和横向。 在此处输入图片说明

This is what i want to happen anytime a cell is pressed, but the problem arises when i clicked out of the view to make it disappear, then press any cell:这就是我想要在按下单元格时发生的情况,但是当我单击视图以使其消失时出现问题,然后按下任何单元格:

在此处输入图片说明

the first orientation, whether it be landscape or portrait, it is fine, but the problem arises when i change the orientation now, for the second or more cell pressed.第一个方向,无论是横向还是纵向,都很好,但是当我现在改变方向时出现问题,按下第二个或更多单元格。

在此处输入图片说明

I tried to use the debut view hierarchy and this is what the error screen looks like.我尝试使用首次亮相的视图层次结构,这就是错误屏幕的样子。

在此处输入图片说明

The main idea that I am following is the tutorial from this site: https://iosrevisited.blogspot.com/2017/10/adaptive-autolayout-programmatically-iphone-x.html我遵循的主要思想是本网站的教程: https : //iosrevisited.blogspot.com/2017/10/adaptive-autolayout-programmatically-iphone-x.html

I was able to complete this tutorial, and it worked fine.我能够完成本教程,并且效果很好。 The difference that I have is that mine is in a view that is suppose to appear and disappear whenever the user wants.我的不同之处在于,我的视图应该在用户需要时出现和消失。

This is the code for the view controller that has the collectionView:这是具有 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
        }
    }

}

for a little clarity, what is was trying to go for was to have a blur view appear and disappear with the view coming up.为了稍微清楚一点,我们想要的是让模糊视图随着视图的出现而出现和消失。

this is the code for the view that will appear when the cell appears:这是单元格出现时将出现的视图的代码:

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)
        }
    }

}

I got the idea in this view from the site I added above.我从上面添加的站点中获得了这个视图中的想法。 I had to change some things since it is a view, but it should work the same.我不得不改变一些东西,因为它是一个视图,但它应该是一样的。 I think the error is in this, but I tried changing the constraints for portrait and landscape, but it didn't work.我认为错误就在于此,但我尝试更改纵向和横向的约束,但没有奏效。 I tried writing it down to see which constraints were removed then updated again, but I just can't seem to find which one it is that is messing with me.我试着把它写下来,看看哪些约束被删除,然后再次更新,但我似乎无法找到是哪一个让我感到困惑。 I know that the problem should be in the top anchor for the red view, or the bottom anchor for the blue view, but I can't figure out which one is faulty or wrong.我知道问题应该出在红色视图的顶部锚点或蓝色视图的底部锚点,但我无法弄清楚哪个是错误的或错误的。

I hope that this is enough information, but please ask me if there is anything else I can help with.我希望这是足够的信息,但请询问我是否还有其他需要帮助的地方。

also, if it isn't much trouble, if you noticed when the view appears, it seems that the navigation bar doesn't blur.另外,如果不是很麻烦,如果您注意到视图出现时,导航栏似乎没有模糊。 This makes it look like the custom view is cut off at the top.这使得自定义视图看起来像是在顶部被切断。 If you know a way to either blur the navigation bar, or try and push the top anchor of the view down so it doesn't look that bad, it would be greatly appreciated.如果您知道一种模糊导航栏的方法,或者尝试将视图的顶部锚点向下推以使其看起来不那么糟糕,我们将不胜感激。

I have tried to use我试过用

self.navigationItem.bottomAnchor

and i tried to add a top anchor with a constant to the view, but the configuration i have above is the best way that i could find to get the view to appear right each time and perfectly.我试图在视图中添加一个带有常量的顶部锚点,但我上面的配置是我能找到的让视图每次都完美显示的最佳方式。 Thank you very much非常感谢

presentInfoView function remove infoView.addView() 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