使用约束实现垂直UIScrollView

时间:2015-08-04 02:18:12

标签: ios swift uiscrollview

我需要在UIView中添加更多内容,但我不确定如何实现UIScrollView以放置更多内容,而这只是横向滚动。

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    /*DECLARACION DE OBJETOS*/


    //Declaracion del Label
    let Titulo = UILabel() as UILabel;
    let Titulo_Clima = UILabel() as UILabel;
    let Texto = UILabel() as UILabel;

    let texto_Titulo = "Hola.";
    let texto_Inicio = "Bienvenidos a Robinsonia, esta aplicacón te ayudará a organizar tu viaje a Robinson Crusoe, selecciona las opciones en el menu principal, haciendo clic en el boton superior izquierdo.";

    let texto_Clima = "Clima";

    /*FIN DECLARACION DE OBJETOS*/


    //FUNCION PARA PERMITIR COLORES HEXÁDECIMALES
    func uicolorFromHex(rgbValue:UInt32)->UIColor{
        let red = CGFloat((rgbValue & 0xFF0000) >> 16)/256.0;
        let green = CGFloat((rgbValue & 0xFF00) >> 8)/256.0;
        let blue = CGFloat(rgbValue & 0xFF)/256.0;

        return UIColor(red:red, green:green, blue:blue, alpha:1.0);
    }
    //***

    override func viewDidLoad() {
        super.viewDidLoad()

         //ITEM QUE ABRE EL MENU.
        title = "Crusoe";
        view.backgroundColor = uicolorFromHex(0xD9E5EA);

        //Imagen icono menu principal
        let b3 = UIBarButtonItem(image:UIImage(named:"Menu"), style:.Plain, target:self, action:"presentLeftMenuViewController");
        navigationItem.leftBarButtonItem = b3;

        //Color de Fuente
        let fuente_titulo = UIFont (name: "Oxygen", size: 35);
        let fuente_tituloClima = UIFont (name: "Oxygen", size: 26);
        let fuente_texto = UIFont (name: "Oxygen", size: 17);
        let color_fuente_texo = uicolorFromHex(0x484A4B);
        let color_fuente_titulos = uicolorFromHex(0x3A3B3C);

        //**** Logica de contenido
        let button = UIButton.buttonWithType(UIButtonType.System) as! UIButton;
        button.frame = CGRectMake(10, 10, 200, 100);
        button.backgroundColor = UIColor.greenColor();
        button.setTitle("Test Button", forState: UIControlState.Normal);
        button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside);

        //Dibujo el Label.
        Titulo.text = texto_Titulo;
        Titulo.font = fuente_titulo
        Titulo.textAlignment = .Center;
        Titulo.textColor = color_fuente_titulos;
        Titulo.setTranslatesAutoresizingMaskIntoConstraints(false);

        //Dibujo el titulo del clima
        Titulo_Clima.text = texto_Clima;
        Titulo_Clima.font = fuente_tituloClima;
        Titulo_Clima.textAlignment = .Left;
        Titulo_Clima.textColor = color_fuente_titulos;
        Titulo_Clima.setTranslatesAutoresizingMaskIntoConstraints(false);

        //Dibujo texto de inicio.
        Texto.text = texto_Inicio;
        Texto.font = fuente_texto;
        Texto.textAlignment = .Center;
        Texto.textColor = color_fuente_texo;
        Texto.numberOfLines=6;
        Texto.setTranslatesAutoresizingMaskIntoConstraints(false);

        //*** DEFINIENDO EL COLOR DEL BORDER
        let borderColor : UIColor = uicolorFromHex(0xFFFFFF);

        //*** VIEW SUPERIOR
        var topView = UIView();
        topView.setTranslatesAutoresizingMaskIntoConstraints(false);

        //*** VIEW UNO
        var bottomView = UIView();
        //bottomView.backgroundColor = UIColor(white: 1, alpha: 0.1);
        bottomView.setTranslatesAutoresizingMaskIntoConstraints(false);


        //*** VIEW DOS
        var bottomView_dos = UIView();
        bottomView_dos.backgroundColor = UIColor(white: 1, alpha: 0.1);
        bottomView_dos.setTranslatesAutoresizingMaskIntoConstraints(false);



        //*** DEFNIENDO LOS OBJETOS CON 0 OPACIDAD
        Titulo.alpha = 0;
        Texto.alpha = 0;
        bottomView.alpha = 0;
        bottomView_dos.alpha = 0;


        //*** INICIALIZANDO LOS VIEWS
        self.view.addSubview(topView);
        self.view.addSubview(bottomView);
        self.view.addSubview(bottomView_dos);

        //*** TEXTOS
        topView.addSubview(Titulo); // titulo del inicio
        topView.addSubview(Texto); // texto del inicio
        bottomView.addSubview(Titulo_Clima); // titulo del clima


        //*** DEFINIENDO LAS ANIMACIONES PARA LOS OBJETOS
        UIView.animateWithDuration(1.0, animations: {
            self.Titulo.alpha = 1.0
            bottomView.alpha = 2.0
            bottomView_dos.alpha = 3.0
        })

        UIView.animateWithDuration(1.5, animations: {
            self.Texto.alpha = 1.0
        })

        //*** DICCIONARIO
        let viewsDictionary = ["top":topView
                                ,"bottom":bottomView
                                ,"bottom_dos":bottomView_dos
                                ,"button":button
                                ,"Titulo":Titulo
                                ,"Texto":Texto
                                ,"Titulo_Clima":Titulo_Clima]


        //*** POSICION DE LOS VIEWS HORIZONTAL
        let view_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[top]-10-|",
                                                                                        options: NSLayoutFormatOptions(0),
                                                                                        metrics: nil,
                                                                                        views: viewsDictionary)
        let view_constraint_H2:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[bottom(bottom_dos)]-[bottom_dos]-10-|",
                                                                                        options: NSLayoutFormatOptions(0),
                                                                                        metrics: nil,
                                                                                        views: viewsDictionary)

            view.addConstraints(view_constraint_H as [AnyObject])
            view.addConstraints(view_constraint_H2 as [AnyObject])

        //*** POSICION DE LOS VIEWS VERTICAL
        let view_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-65-[top(bottom)]-[bottom]-10-|",
                                                                                        options: NSLayoutFormatOptions.AlignAllLeading,
                                                                                        metrics: nil,
                                                                                        views: viewsDictionary)
        let view_constraint_VV:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-65-[top(bottom_dos)]-[bottom_dos]-10-|",
                                                                                        options: NSLayoutFormatOptions(0),
                                                                                        metrics: nil,
                                                                                        views: viewsDictionary)

            view.addConstraints(view_constraint_V as [AnyObject])
            view.addConstraints(view_constraint_VV as [AnyObject])

        //*** POSICION DEL TITULO
        let view_constraint_H_Titulo:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[Titulo]-0-|",
                                                                                            options: NSLayoutFormatOptions.AlignAllLeading,
                                                                                            metrics: nil,
                                                                                            views: viewsDictionary)

        let view_constraint_V_Titulo:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[Titulo]-[Texto]",
                                                                                            options: NSLayoutFormatOptions.AlignAllLeading,
                                                                                            metrics: nil,
                                                                                            views: viewsDictionary)

            topView.addConstraints(view_constraint_H_Titulo as [AnyObject])
            topView.addConstraints(view_constraint_V_Titulo as [AnyObject])

        //*** POSICION DEL TITULO PARA EL CLIMA
        let view_constraintTituloClima_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-5-[Titulo_Clima]-5-|",
                                                                                                options: NSLayoutFormatOptions.AlignAllLeading,
                                                                                                metrics: nil,
                                                                                                views: viewsDictionary)

        let view_constraintTituloClima_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[Titulo_Clima]",
            options: NSLayoutFormatOptions.AlignAllLeading,
            metrics: nil,
            views: viewsDictionary)

        bottomView.addConstraints(view_constraintTituloClima_H as [AnyObject])
        bottomView.addConstraints(view_constraintTituloClima_V as [AnyObject])

        //*** POSICION DEL TEXTO
        let view_constraint_H_Texto:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[Texto]-0-|",
                                                                                            options: NSLayoutFormatOptions.AlignAllLeading,
                                                                                            metrics: nil,
                                                                                            views: viewsDictionary)

            topView.addConstraints(view_constraint_H_Texto as [AnyObject])

        //***

    }

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

    /*Funciones Extras*/
    func buttonAction(sender:UIButton!)
    {
        println("Button tapped")
    }



}

1 个答案:

答案 0 :(得分:2)

使用滚动视图的子视图创建约束的关键是约束用于指定滚动视图的contentSize的大小。 (通常约束规定了子视图的frame,但是使用滚动视图反过来,控制指示滚动行为的contentSize。)因此,如果你想要标签不超出屏幕宽度,你不想只在标签和滚动视图之间添加约束,也要在滚动视图的超级视图中添加约束。

这样做的一种方法是不将视图直接放在滚动视图中,而是放置一个"容器视图" (实际上只是一个简单的UIView,但我们经常将它称为"容器"因为它只在滚动视图中包含其他视图对象,然后将标签添加到容器视图中。因此,如果您有一个垂直布局的九个标签的滚动视图,您最终会得到一个看起来像这样的视图层次结构:

<view: 0x7fdb58b123e0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fdb58b079c0>>
   | <scrollView: 0x7fdb59012600; frame = (0 0; 375 667); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fdb58810ba0>; layer = <CALayer: 0x7fdb5880bc80>; contentOffset: {0, 0}; contentSize: {375, 1907}>
   |    | <contentView: 0x7fdb58813fd0; frame = (0 0; 375 1907); layer = <CALayer: 0x7fdb58814130>>
   |    |    | <label1: 0x7fdb588143a0; frame = (8 8; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb588149d0>>
   |    |    | <label2: 0x7fdb58816980; frame = (8 219; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb58816b80>>
   |    |    | <label3: 0x7fdb58817110; frame = (8 430; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb58817310>>
   |    |    | <label4: 0x7fdb58817830; frame = (8 641; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb58817a30>>
   |    |    | <label5: 0x7fdb58817e00; frame = (8 852; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb58804c10>>
   |    |    | <label6: 0x7fdb588183f0; frame = (8 1063; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb588185f0>>
   |    |    | <label7: 0x7fdb588189f0; frame = (8 1274; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb58818bf0>>
   |    |    | <label8: 0x7fdb588190a0; frame = (8 1485; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb588192a0>>
   |    |    | <label9: 0x7fdb588196a0; frame = (8 1696; 359 203); text = 'Lorem ipsum dolor sit ame...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdb588198a0>>

为了正确布局,需要添加三组约束:

  1. 根据其超视图布局滚动视图(在本例中为视图控制器的根视图):

    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: [], metrics: nil, views: views))
    
  2. 接下来,针对滚动视图contentSize布置内容视图:

    scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[contentView]|", options: [], metrics: nil, views: views))
    scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[contentView]|", options: [], metrics: nil, views: views))
    
  3. 指定contentView的宽度应与滚动视图的超级视图(view)的宽度相同:

    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[contentView(==view)]", options: [], metrics: nil, views: views))
    

    请注意,虽然contentViewscrollView的子视图,但此约束会添加到滚动视图的超级视图中,因为此约束指的是超视图的宽度。

    另请注意,如果您愿意,您实际上可以将此约束与上面第2点中列出的水平约束结合使用,但我已在此处将其分开以尽量使其尽可能清晰。

  4. 最后,现在定义标签&#39;关于内容视图的约束:

    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[label1]-[label2]-[label3]-[label4]-[label5]-[label6]-[label7]-[label8]-[label9]-|", options: [], metrics: nil, views: views))
    
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label1]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label2]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label3]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label4]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label5]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label6]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label7]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label8]-|", options: [], metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label9]-|", options: [], metrics: nil, views: views))
    

    请注意,垂直约束不仅定义了距第一个标签和内容视图顶部的距离,还定义了从最后一个标签到内容视图底部的距离。

  5. 但这里的关键点是第2点的组合(表示&#34;使滚动视图的contentSize与此新内容视图的大小相同。&#39;&#34; )和第3点(表示&#34;但是使内容视图&#39;不比屏幕宽)。如果您不执行这两个步骤,则无法获得您正在寻找的垂直滚动。

    另请注意,如果您希望标签自动调整大小,可以将numberOfLines设置为零,标签的内在大小将更改为适合文字。

    显然,您的视图层次结构并不像这样(您有两个底部视图等),但我说明了如何将滚动视图设置为布局的基本概念正确使用自动布局约束。