简体   繁体   English

UIScrollView 内的动态 UITableView

[英]Dynamic UITableView inside UIScrollView

I'm having trouble implementing dynamic UITableView inside UIScrollView, without sitting fixed height constraints to the UITableView it disappears and I don't want to make fixed height to it because it is receiving data from API and I don't know the count of them.我在 UIScrollView 中实现动态 UITableView 时遇到问题,没有固定高度约束 UITableView 它消失了,我不想给它固定高度,因为它从 API 接收数据,我不知道它们的数量. What I want to achieve is the height of the UITableView should be dynamic not the UITableViewCell.我想要实现的是 UITableView 的高度应该是动态的而不是 UITableViewCell。

Here is my code:这是我的代码:

RecipesDetailsView:食谱详情查看:

class RecipesDetailsView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        layoutUI()
    }

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

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView == self.scrollView {
            ingredientsTableView.isScrollEnabled = (self.scrollView.contentOffset.y >= 200)
        }

        if scrollView == self.ingredientsTableView {
            self.ingredientsTableView.isScrollEnabled = (ingredientsTableView.contentOffset.y > 0)
        }
    }

    lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.backgroundColor = .customVeryLightGray()
        scrollView.showsVerticalScrollIndicator = false
        scrollView.alwaysBounceVertical = false
//        scrollView.bounces = false
        return scrollView
    }()

    lazy var containerView: UIView = {
        let containerView = UIView()
        containerView.backgroundColor = .clear
        containerView.translatesAutoresizingMaskIntoConstraints = false
        return containerView
    }()

    lazy var recipeTitleLabel: UILabel = {
        let recipeTitleLabel = UILabel()
        recipeTitleLabel.translatesAutoresizingMaskIntoConstraints = false
        recipeTitleLabel.text = "Myanmar Traditional Fish Curry"
        recipeTitleLabel.font = UIFont(name: "AvenirNext-DemiBold", size: 25)
        recipeTitleLabel.textColor = .customDarkGray()
        recipeTitleLabel.numberOfLines = 0
        recipeTitleLabel.textAlignment = .left
        return recipeTitleLabel
    }()

    lazy var recipeImage: UIImageView = {
        let recipeImage = UIImageView()
        recipeImage.contentMode = .scaleToFill
        recipeImage.clipsToBounds = true
        recipeImage.image = UIImage(named: "pizza")
        recipeImage.layer.cornerRadius = 8.0
        recipeImage.layer.masksToBounds = true
        recipeImage.translatesAutoresizingMaskIntoConstraints = false
        return recipeImage
    }()

    lazy var instructionLabel: UILabel = {
        let instructionLabel = UILabel()
        instructionLabel.text = "Instructions"
        instructionLabel.font = UIFont(name: "AvenirNext-DemiBold", size: 16)
        instructionLabel.textColor = .customDarkGray()
        instructionLabel.textAlignment = .left
        instructionLabel.translatesAutoresizingMaskIntoConstraints = false
        return instructionLabel
    }()

    lazy var instructionsTextView: UITextView = {
        let instructionsTextView = UITextView()
        instructionsTextView.text = "Myanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmarMyanmar Traditional Fish CurryMyanmar Traditional Fish CurryMyanmar"
        instructionsTextView.textColor = .customLightDarkGray()
        instructionsTextView.font = UIFont(name: "AvenirNext-Regular", size: 14)
        instructionsTextView.textAlignment = .left
        instructionsTextView.isEditable = false
        instructionsTextView.isScrollEnabled = false
        instructionsTextView.translatesAutoresizingMaskIntoConstraints = false
        return instructionsTextView
    }()

    lazy var ingredientsLabel: UILabel = {
        let ingredientsLabel = UILabel()
        ingredientsLabel.text = "Ingredients"
        ingredientsLabel.font = UIFont(name: "AvenirNext-DemiBold", size: 16)
        ingredientsLabel.textColor = .customDarkGray()
        ingredientsLabel.textAlignment = .left
        ingredientsLabel.translatesAutoresizingMaskIntoConstraints = false
        return ingredientsLabel
    }()

    lazy var buyingIngredientsButton: UIButton = {
        let buyingIngredientsButton = UIButton(type: .system)
        buyingIngredientsButton.translatesAutoresizingMaskIntoConstraints = false
        buyingIngredientsButton.setTitle("Start buying", for: .normal)
        buyingIngredientsButton.setTitleColor(.CustomGreen(), for: .normal)
        buyingIngredientsButton.titleLabel?.font = UIFont(name: "AvenirNext-DemiBold", size: 12)
        return buyingIngredientsButton
    }()

    lazy var numberOfGredientsLabel: UILabel = {
        let numberOfGredientsLabel = UILabel()
        numberOfGredientsLabel.text = "Ingredients"
        numberOfGredientsLabel.font = UIFont(name: "AvenirNext-Regular", size: 14)
        numberOfGredientsLabel.textColor = .customDarkGray()
        numberOfGredientsLabel.textAlignment = .left
        numberOfGredientsLabel.translatesAutoresizingMaskIntoConstraints = false
        return numberOfGredientsLabel
    }()

    lazy var ingredientsTableView: UITableView = {
        let ingredientsTableView = UITableView()
        ingredientsTableView.translatesAutoresizingMaskIntoConstraints = false
        ingredientsTableView.delegate = self
        ingredientsTableView.dataSource = self
        ingredientsTableView.rowHeight = UITableView.automaticDimension
        ingredientsTableView.estimatedRowHeight = 100
        ingredientsTableView.estimatedRowHeight = 0
        ingredientsTableView.estimatedSectionHeaderHeight = 0
        ingredientsTableView.estimatedSectionFooterHeight = 0
        ingredientsTableView.showsVerticalScrollIndicator = false
        ingredientsTableView.separatorStyle = .none
        ingredientsTableView.backgroundColor = .white
        ingredientsTableView.bounces = true
        ingredientsTableView.isScrollEnabled = false
        ingredientsTableView.register(IngredientsTableViewCell.self, forCellReuseIdentifier: "IngredientsTableViewCell")
        ingredientsTableView.frame.size.height = ingredientsTableView.contentSize.height
        return ingredientsTableView
    }()

    func setupScrollViewConstraints() {
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
            scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }

    func setupContainerViewConstraints() {
        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1)
        ])
    }

    func setupRecipeTitleLabelConstraints() {
        NSLayoutConstraint.activate([
            recipeTitleLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 16),
            recipeTitleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            recipeTitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: containerView.trailingAnchor, constant: -16)
        ])
        recipeTitleLabel.setContentHuggingPriority(.init(240.0), for: .horizontal)
        recipeTitleLabel.setContentCompressionResistancePriority(.init(740.0), for: .horizontal)
    }

    func setupRecipeImageConstraints() {
        NSLayoutConstraint.activate([
            recipeImage.topAnchor.constraint(equalTo: recipeTitleLabel.bottomAnchor, constant: 16),
            recipeImage.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            recipeImage.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16),
            recipeImage.heightAnchor.constraint(equalToConstant: frame.height / 4)
        ])
    }

    func setupInstructionsLabelConstraints() {
        NSLayoutConstraint.activate([
            instructionLabel.topAnchor.constraint(equalTo: recipeImage.bottomAnchor, constant: 16),
            instructionLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            instructionLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16)
        ])
    }

    func setupInstructionsTextViewConstraints() {
        NSLayoutConstraint.activate([
            instructionsTextView.topAnchor.constraint(equalTo: instructionLabel.bottomAnchor, constant: 8),
            instructionsTextView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            instructionsTextView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16)
        ])
    }

    func setupIngredientsLabelConstraints() {
        NSLayoutConstraint.activate([
            ingredientsLabel.topAnchor.constraint(equalTo: instructionsTextView.bottomAnchor, constant: 16),
            ingredientsLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
        ])
    }

    func setupBuyingIngredientsButtonConstraints() {
        NSLayoutConstraint.activate([
            buyingIngredientsButton.centerYAnchor.constraint(equalTo: ingredientsLabel.centerYAnchor),
            buyingIngredientsButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16)
        ])
    }

    func setupNumberOfIngredientsLabelConstraints() {
        NSLayoutConstraint.activate([
            numberOfGredientsLabel.topAnchor.constraint(equalTo: ingredientsLabel.bottomAnchor, constant: 8),
            numberOfGredientsLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),

        ])
    }

    func setupIngredientsTableViewConstraints() {
        NSLayoutConstraint.activate([
            ingredientsTableView.topAnchor.constraint(equalTo: numberOfGredientsLabel.bottomAnchor, constant: 8),
            ingredientsTableView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            ingredientsTableView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16),
            ingredientsTableView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -16),
//            ingredientsTableView.heightAnchor.constraint(equalTo: ingredientsTableView.heightAnchor)
        ])
    }

    func addSubViews() {
        addSubview(scrollView)
        scrollView.addSubview(containerView)
        containerView.addSubview(recipeTitleLabel)
        containerView.addSubview(recipeImage)
        containerView.addSubview(instructionLabel)
        containerView.addSubview(instructionsTextView)
        containerView.addSubview(ingredientsLabel)
        containerView.addSubview(buyingIngredientsButton)
        containerView.addSubview(numberOfGredientsLabel)
        containerView.addSubview(ingredientsTableView)
    }

    func layoutUI() {
        addSubViews()
        setupScrollViewConstraints()
        setupContainerViewConstraints()
        setupRecipeTitleLabelConstraints()
        setupRecipeImageConstraints()
        setupInstructionsLabelConstraints()
        setupInstructionsTextViewConstraints()
        setupIngredientsLabelConstraints()
        setupBuyingIngredientsButtonConstraints()
        setupNumberOfIngredientsLabelConstraints()
        setupIngredientsTableViewConstraints()
    }
}

extension RecipesDetailsView: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "IngredientsTableViewCell", for: indexPath) as! IngredientsTableViewCell
        cell.theNumberOfIngredient.text = "1"
        cell.theNameOfIngredient.text = "Tomato"
        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension

    }

}

IngredientsTableViewCell:成分表视图单元格:

class IngredientsTableViewCell: UITableViewCell {

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        layoutUI()
//        selectionStyle = .none
//        self.backgroundColor = .white

    }

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

    lazy var theNumberOfIngredient: UILabel = {
        let theNumberOfIngredient = UILabel()
        theNumberOfIngredient.text = "Ingredients"
        theNumberOfIngredient.font = UIFont(name: "AvenirNext-DemiBold", size: 16)
        theNumberOfIngredient.textColor = .customDarkGray()
        theNumberOfIngredient.textAlignment = .left
        theNumberOfIngredient.translatesAutoresizingMaskIntoConstraints = false
        return theNumberOfIngredient
    }()

    lazy var theNameOfIngredient: UILabel = {
        let theNameOfIngredient = UILabel()
        theNameOfIngredient.text = "Ingredients"
        theNameOfIngredient.font = UIFont(name: "AvenirNext-DemiBold", size: 16)
        theNameOfIngredient.textColor = .customDarkGray()
        theNameOfIngredient.textAlignment = .left
        theNameOfIngredient.translatesAutoresizingMaskIntoConstraints = false
        return theNameOfIngredient
    }()

    func setupTheNumberOfIngredientConstraints() {
        NSLayoutConstraint.activate([
            theNumberOfIngredient.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),
            theNumberOfIngredient.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }

    func setupTheNameOfIngredientConstraints() {
        NSLayoutConstraint.activate([
            theNameOfIngredient.leadingAnchor.constraint(equalTo: theNumberOfIngredient.leadingAnchor, constant: 16),
            theNameOfIngredient.centerYAnchor.constraint(equalTo: theNumberOfIngredient.centerYAnchor)
        ])
    }

    func addSubviews() {
        addSubview(theNumberOfIngredient)
        addSubview(theNameOfIngredient)
    }

    func layoutUI() {
        addSubviews()
        setupTheNumberOfIngredientConstraints()
        setupTheNameOfIngredientConstraints()
    }

}

First, this is the wrong approach, I think you should create UITableView with grouped style and in the section 0 add your custom UI and the section 1 apply IngredientsTableViewCell with the data From API.首先,这是错误的方法,我认为您应该使用分组样式创建 UITableView,并在the section 0添加您的自定义 UI, the section 1使用来自 API 的数据应用IngredientsTableViewCell视图单元。

otherwise, you can set static height for UITableView Mathematically.否则,您可以通过数学方式为 UITableView 设置静态高度。

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

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