UIScrollView和它的孩子们:为什么他们被置于彼此之上? (自动版式)

时间:2014-10-07 10:32:16

标签: ios uiview swift uiscrollview autolayout

我制作的应用可以让某人将产品添加到订单中。每个产品都拥有它自己的UIView,所有这些产品都放在一个用户界面中(并在一个数组中供将来参考,如总价格等)。我对添加产品毫不犹豫:

/* Create the new product */        
var tmp = Product(data: product)
/* Add it to the scrollView */
scrollView.addSubview(tmp)

我正在使用AutoLayout作为UIScrollView本身,但没有设置约束(我已经清除它以便检查)。

澄清:产品是UIView的子类,只是为了标准化每个产品的外观。

然而,当我添加超过1个产品时,新产品将被放置在第一个产品之上而不是第一个之上。我有一种感觉,我错过了使用带有自动布局的UIScrollView的关键部分。有人能指出我正确的方向吗?

编辑:最后我通过使用(重新)计算位置的方法来解决它,因为我与UICollectionView有相同的行为。我正在使用Android中的同一个应用程序,你可以在其中使用一个子元素就像一个块(在CSS意义上)的元素。通过在iOS中寻找相同的解决方案我很顽固:)

1 个答案:

答案 0 :(得分:2)

当您致电[scrollView addSubview:productView];时,UIScrollView不会自动将您的子视图定位在正确的位置

在将子视图添加到UIScrollView之前,您需要使用initWithFrame告诉子视图正确的位置,在这种情况下,您似乎正在使用Autolayout。

如果您对替代方案持开放态度,我认为UICollectionView可以实现您的目标。每个"单元"在集合视图中是您的产品视图。集合视图具有滚动视图所具有的所有功能。

如果您在产品视图中使用框架,那么您可以这样做:

var view1:UIView = UIView(frame: CGRectMake(0, 0, 320, 480)];

// -----------------------------------------------------------------------
// Notice here, view2 has a Y position that takes the height of view1
//
// So we're telling iOS to put view2 right below view1 before we
// add it as a subview of our scrollView
// -----------------------------------------------------------------------
var view2:UIView = UIView(frame: CGRectMake(0, view1.frame.origin.y, 320, 480));

self.scrollView.addSubview(view1);
self.scrollView.addSubview(view2);

UICollectionView Autolayout演示:

为了完整起见,我将使用 Swift 包含一个基本的UICollectionView Autolayout演示。

的viewController

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    var arrItems:NSMutableArray = NSMutableArray();
    var collectionView:UICollectionView?;

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.arrItems.addObject("Apple");
        self.arrItems.addObject("Banana");
        self.arrItems.addObject("Orange");
        self.arrItems.addObject("Mango");
        self.arrItems.addObject("Watermelon");

        initViews();
        initConstraints();
    }

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

    func initViews()
    {
        // ------------------------------------------------------
        // Init the collection View
        // ------------------------------------------------------

        var flowLayout:UICollectionViewFlowLayout = UICollectionViewFlowLayout();
        flowLayout.itemSize = CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height / 2.0);

        self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout);
        self.collectionView?.registerClass(ProductCell.self, forCellWithReuseIdentifier: "cellID");
        self.collectionView?.delegate = self;
        self.collectionView?.dataSource = self;
        self.collectionView?.backgroundColor = UIColor.whiteColor();
        self.collectionView?.pagingEnabled = true;

        self.view.addSubview(self.collectionView!);
    }

    func initConstraints()
    {
        self.collectionView?.setTranslatesAutoresizingMaskIntoConstraints(false);

        var views:NSMutableDictionary = NSMutableDictionary();

        views.setValue(self.collectionView!, forKey: "collectionView");

        self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[collectionView]|", options: nil, metrics: nil, views: views));
        self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[collectionView]|", options: nil, metrics: nil, views: views));
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {


        return self.arrItems.count;
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        // ---------------------------------------------------
        // Note, Swift is able to detect all developer's own
        // class files, so no need to import ProductCell
        // ---------------------------------------------------

        // create a ProductCell
        var cell:ProductCell = collectionView.dequeueReusableCellWithReuseIdentifier("cellID", forIndexPath: indexPath) as ProductCell;

        // setup product info
        cell.productName.text = self.arrItems[indexPath.row] as NSString;
        cell.productDescription.text = "This is some text about the product. It can be a very long block of text or maybe a really short one. Up to you to design it anyway you like.";

        return cell;
    }

}

产品单元类

import UIKit

class ProductCell: UICollectionViewCell {
    var container:UIView = UIView();
    var productName:UILabel = UILabel();
    var productDescription:UILabel = UILabel();

    override init(frame: CGRect) {
        super.init(frame: frame);

        initViews();
        initConstraints();
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder);
    }

    func initViews()
    {
        self.container.backgroundColor = UIColor.lightGrayColor();
        self.container.layer.cornerRadius = 5.0;

        self.productName.font = UIFont.systemFontOfSize(14);
        self.productName.textColor = UIColor.whiteColor();
        self.productName.textAlignment = NSTextAlignment.Center;
        self.productName.numberOfLines = 0;
        self.productName.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical);
        self.productName.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.8, alpha: 1.0);
        self.productName.layer.cornerRadius = 5.0;
        self.productName.clipsToBounds = true;

        self.productDescription.font = UIFont.systemFontOfSize(14);
        self.productDescription.numberOfLines = 0;

        self.container.addSubview(self.productName);
        self.container.addSubview(self.productDescription);

        self.contentView.addSubview(self.container);
    }

    func initConstraints()
    {
        self.container.setTranslatesAutoresizingMaskIntoConstraints(false);
        self.productName.setTranslatesAutoresizingMaskIntoConstraints(false);
        self.productDescription.setTranslatesAutoresizingMaskIntoConstraints(false);

        var views:NSMutableDictionary = NSMutableDictionary();
        views.setValue(self.container, forKey: "container");
        views.setValue(self.productName, forKey: "productName");
        views.setValue(self.productDescription, forKey: "productDescription");

        // container constraints
        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[container]-20-|", options: nil, metrics: nil, views: views));
        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[container]-20-|", options: nil, metrics: nil, views: views));

        // subview constraints

        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[productName]-10-|", options: nil, metrics: nil, views: views));

        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[productDescription]-10-|", options: nil, metrics: nil, views: views));

        self.container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-10-[productName(50)]-10-[productDescription]-10-|", options: nil, metrics: nil, views: views));
    }
}

你应该得到类似的东西:

screenshot of UICollectionView Swift demo