2016-05-30 59 views
0
let N = 4 
let holder = UIView(frame: CGRectMake(0, 0, someWidth, N * 100)) 
for var i = 0; i <= N; i++ { 
    let content = UIView(frame: CGRect.zero) //height should be 100 
    content.backgroundColor = randomColor() 
    content.translatesAutoresizingMaskIntoConstraints = true 
    holder.addSubview(content) 
} 

上面的代碼將添加N UIViews到holder。我想以編程方式使用NSLayoutConstraints垂直顯示內容,一個在另一個之上。如何自動佈局垂直列表的UIViews,一個在另一個之上?

每個內容應具有100高度每個內容應該對所有4個邊緣約束。第一個內容應該有頂部/前導/尾隨約束(常量= 0)到holder。最後的內容應該有底部/前導/尾隨約束(常量= 0)至holder

內容的其餘部分應該具有頂部/底部約束(常數= 8)向另一同級內容。

如何創建這些約束?

+0

你有什麼理由寧願手動佈局'NSStackView'? –

回答

1

Vertical page

Samething我爲水平頁來完成。因此,這裏是代碼

var scrollView = UIScrollView() 
var contectView = UIView(); 

添加holderview的子視圖

self.scrollView.translatesAutoresizingMaskIntoConstraints = false; 
    self.view.addSubview(self.scrollView); 

    self.contectView.translatesAutoresizingMaskIntoConstraints = false; 
    self.scrollView.addSubview(self.contectView); 

爲holderView

創建約束
let views = ["contectView" : self.contectView , "scrollview" : self.scrollView ]; 

    // create constraint for scrollview 
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollview]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollview]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 

    // create constraint for contectview with low priority for width and height 
    self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[contectView([email protected])]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 
    self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[contectView([email protected])]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 

製作水平串約束

 var verticalConstraintsFormat = ""; // create horizantal constraint string 
    let subViews = NSMutableDictionary(); 
    subViews["scrollView"] = self.scrollView; 

創建動態頁面

let totalPage : NSInteger = 10; 

    for i in 0...totalPage { 

     // Create your page here 
     let objProductView = UIView() 
     objProductView.translatesAutoresizingMaskIntoConstraints = false; 
     objProductView.backgroundColor = UIColor(white: CGFloat(arc4random()%100)/CGFloat(100), alpha: 1) 
     self.contectView.addSubview(objProductView); 

     let key = NSString(format: "productView%d", i) as NSString 
     subViews[key] = objProductView; 


     if(i==0){ 
      verticalConstraintsFormat = verticalConstraintsFormat.stringByAppendingFormat("V:|-0-[%@(==100)]", key); 
     } 
     else if (i==totalPage) { 
      verticalConstraintsFormat = verticalConstraintsFormat.stringByAppendingFormat("-0-[%@(==100)]-0-|", key); 

     } 
     else{ 
      verticalConstraintsFormat = verticalConstraintsFormat.stringByAppendingFormat("-0-[%@(==100)]", key); 

     } 

     let verticalConstraintsFormat1 = NSString(format:"H:|[%@(==scrollView)]", key); 
     self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(verticalConstraintsFormat1 as String, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: subViews as AnyObject as! [String : AnyObject])); 


    } 
    self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(verticalConstraintsFormat as String, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: subViews as AnyObject as! [String : AnyObject])); 

希望這會有所幫助。

1

你可以做這樣的事情,

let content = UIView() 
    content.backgroundColor = UIColor.redColor() 
    content.translatesAutoresizingMaskIntoConstraints = false 
    view.addSubview(content) 


    let topConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0) 
    view.addConstraint(topConstraint) 

    let leadingConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0) 
    view.addConstraint(leadingConstraint) 

    let bottomConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0) 
    view.addConstraint(bottomConstraint) 

let trailingConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0) 
    view.addConstraint(trailingConstraint)   

    let heightConstraint = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100) 
    view.addConstraint(heightConstraint) 

在這裏,你應該考慮holder而不是view

這種約束是中間視圖。對於第一和最後一個視圖的場景應該是不同的東西一樣,

//Top constraint for first view should be like, 

    let topConstraintForfirstView = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0) 
    view.addConstraint(topConstraintForfirstView) 

    //Bottom constraint for last view should be like, 

    let bottomConstraintForLastview = NSLayoutConstraint(item: content, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0) 
    view.addConstraint(bottomConstraintForLastview) 

你可以通過改變約束constant管理空間或距離。如果你想要20像素之間的垂直間距視圖然後你的常數top constraints should be 20

你可以參考this answer作爲參考。

不要給高度和底部。如果你給定高度,那麼你不需要底部,如果你給底部,那麼你不需要固定高度。

希望這將有助於:)

1

在我們的項目中,我們遇到了類似的問題,我們不得不大量的意見添加到使用編程方式添加約束的滾動視圖的內容視圖。爲每個視圖編寫約束不僅使視圖控制器變得臃腫,而且也是靜態的。要添加另一個視圖,我們必須再次編寫約束條件。

我們最終創建了UIView的子類,現在爲我們管理了這個子類。我們將其命名爲NNVerticalStackView.h.m

這個類的要點是下面的方法。

-(void)addView:(UIView *)view 
    belowView:(UIView *)viewAbove 
    aboveView:(UIView *)viewBelow 
    withHeight:(CGFloat)height{ 

    view.translatesAutoresizingMaskIntoConstraints = NO; 
    [self addSubview:view]; 

    if(height != NNStackViewContentHeightMetric && height > 0) { 
     NSArray * heightConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view(height)]" options:0 metrics:@{@"height":@(height)} views:NSDictionaryOfVariableBindings(view)]; 
     [view addConstraint:heightConstraint.firstObject]; 
    } 

    NSArray * defaultConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]; 
    NSLayoutConstraint * upperConstraint,* lowerConstraint; 

    if(viewAbove==self) { 
     [self removeConstraint:_topConstraint]; 
     upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject; 
     _topConstraint = upperConstraint; 
    } 
    else 
     upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewAbove]-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewAbove)].firstObject; 

    if(viewBelow==self) { 
     [self removeConstraint:_bottomConstraint]; 
     lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject; 
     _bottomConstraint = lowerConstraint; 
    } 
    else 
     lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-[viewBelow]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewBelow)].firstObject; 

    [self addConstraints:defaultConstraints]; 
    [self addConstraints:@[upperConstraint,lowerConstraint]]; 
} 

對於最頂部的視圖,viewAbove是容器視圖(即self),其他明智它代表了在視圖的視圖以上添加。 對於最下面的視圖,viewBelow是容器視圖,其他視圖是當前視圖下方的視圖被添加的視圖。

因此,對於這個子類,您打算做的事情可以很容易地編碼爲。

let N = 4 
let holder = NNVerticalStackView(frame: CGRectMake(0, 0, someWidth, CGFloat(N) * 100.0)) 
for _ in 0...N { 
    let content = UIView(frame: CGRect.zero) //height should be 100 
    holder.insertStackItem(content, atIndex: 0, withItemHeight: 100.0) 
} 

對於偏移量,您可能需要更改自定義類以定義您自己的偏移量。

相關問題