[Swift] ScrollView avec contenu dynamique

Hello,


 


Je suis en train de devenir fou :)


 


Le problème est simple, j'ai une scrollView + contentView et je souhaite rajouter des contenu dynamiquement. Par contre impossible de faire en sorte que la contentSize de la scrollView grossisse. Et j'ai essayé beaucoup de choses !


 


Voila le code actuel (tout l'autolayout est fait dans le code).



import UIKit

class ViewController: UIViewController {
    
    var scrollView = UIScrollView()
    var contentView = UIView()


    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.backgroundColor = UIColor.blueColor()
        view.addSubview(scrollView)
        
        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.backgroundColor = UIColor.redColor()
        scrollView.addSubview(contentView)
        
        let viewDictionary = ["scrollView": scrollView, "contentView": contentView]
        
        var allConstraints = [NSLayoutConstraint]()


        let svVerticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|-0-[scrollView]-0-|",
            options: [],
            metrics: nil,
            views: viewDictionary)
        allConstraints += svVerticalConstraint


        let svHorizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|-0-[scrollView]-0-|",
            options: [],
            metrics: nil,
            views: viewDictionary)
        allConstraints += svHorizontalConstraint
        
        let cvVerticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|[contentView]|",
            options: [],
            metrics: nil,
            views: viewDictionary)
        allConstraints += cvVerticalConstraint
        
        let cvHorizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|[contentView]|",
            options: [],
            metrics: nil,
            views: viewDictionary)
        allConstraints += cvHorizontalConstraint
        
        let cvWidthConstraint = NSLayoutConstraint.init(item: contentView, attribute: .Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1, constant: 0)
        
        allConstraints += [cvWidthConstraint]
        
        let cvHeightConstraint = NSLayoutConstraint.init(item: contentView, attribute: .Height, relatedBy: .GreaterThanOrEqual, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 1)
        
        allConstraints += [cvHeightConstraint]


//        let cvCenterXConstraint = NSLayoutConstraint.init(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1, constant: 0)
//        
//        allConstraints += [cvCenterXConstraint]
        
//        let cvCenterYConstraint = NSLayoutConstraint.init(item: contentView, attribute: .CenterY, relatedBy: .Equal, toItem: scrollView, attribute: .CenterY, multiplier: 1, constant: 0)
//        
//        allConstraints += [cvCenterYConstraint]
        
        NSLayoutConstraint.activateConstraints(allConstraints)
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func addMessage() {
        
        let random = Int(arc4random_uniform(6))
        
        let text: String!
        switch random {
        case 0:
            text = "Good, better, best. Never let it rest. 'Til your good is better and your better is best."
            break
        case 1:
            text = "Believe in yourself! Have faith in your abilities! Without a humble but reasonable confidence in your own powers you cannot be successful or happy."
            break
        case 2:
            text = "Infuse your life with action. Don't wait for it to happen. Make it happen. Make your own future. Make your own hope. Make your own love. And whatever your beliefs, honor your creator, not by passively waiting for grace to come down from upon high, but by doing what you can to make grace happen... yourself, right now, right down here on Earth."
            break
        case 3:
            text = "If you can dream it, you can do it."
            break
        case 4:
            text = "A creative man is motivated by the desire to achieve, not by the desire to beat others."
            break
        case 5:
            text = "Hello Dude! I'm your friend. I'm here for you."
            break
        default:
            text = ""
            
        }
        let message = Message()
        message.text = text
        


        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 0
        label.textAlignment = .Left
        label.lineBreakMode = .ByWordWrapping
        label.text = text
        label.font = UIFont.systemFontOfSize(12)
        label.textColor = UIColor.blackColor()
        label.sizeToFit()
        
        if let lastView = contentView.subviews.last
        {
            contentView.addSubview(label)


            let viewDictionary = ["label": label, "previousView": lastView]
            
            let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label]-|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: viewDictionary)
            contentView.addConstraints(horizontalConstraints)
            
            let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:[previousView]-20-[label]", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: viewDictionary)
            contentView.addConstraints(verticalConstraints)


        }
        else
        {
            // first view to be added
            contentView.addSubview(label)
            
            let viewDictionary = ["label": label]
            
            let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label]-|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: viewDictionary)
            contentView.addConstraints(horizontalConstraints)
            
            let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[label]", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: viewDictionary)
            contentView.addConstraints(verticalConstraints)




        }
    }
}

Si quelqu'un a une idée ou un tuto (qui marche), je suis preneur :)


Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2016 modifié #2
    Excuses-moi Jeoffrey mais, les UILabels dans une UIScrollView ? Tu ne profiterais plus d'utiliser une UITableView dont les cellules se règlent leurs hauteurs eux-mêmes ?
  • Les UILabel c'est juste pour le début, il faut que se soit une scrollview malheureusement. 


  • Joanna CarterJoanna Carter Membre, Modérateur
    UIStackView ?
  • Euh, j'suis pas sûr d'avoir tout suivi, mais :



    ScrollView
    | ContentView | Label 1
    | | Label 2
    |             | Label 3
    |
    |

    C'est ça ?


    Je ne vois pas la frame de la contentView bouger, ou alors j'ai zappé un truc, du coup, la contentSize de la scrollView ne change pas.


  • La contentSize devrait changer automatiquement en fonction de la taille de la contentView, mais en fait c'est la contentView qui ne grandit pas malgré que j'y rajoute du contenu.


     


    Et pour la stackView, j'avais commencé à  regardé par la, je vais regarder si ca peut aller.


  • Avec une stackview ca fonctionne effectivement.


     


    (stack view dans scroll view)


  • Si j'ai réfère à  ce qui est dit (pas testé, mais ça ne semblerait pas idiot) sur SO (post sans "+1/-1, à  0).


    Mais il faudrait que ta dernière subView (label) soit reliée à  la parentView (contentView) avec un bottomMargin si j'ai bien suivi.


  • AliGatorAliGator Membre, Modérateur

    D'après ce que je vois de ton code tu n'as pas mis de contrainte entre le bas de ton dernier label et le bas de ta contentView. Du coup normal que la contentView ne s'agrandisse pas pour coller au bas des labels que tu ajoutes.


Connectez-vous ou Inscrivez-vous pour répondre.