簡體   English   中英

以編程方式從XIB調整自定義UIView的大小

[英]Programmatically resize custom UIView from XIB

我有以下問題:我已經在XIB文件中創建了一個自定義UIView類及其布局。 假設我在XIB中的自定義視圖的大小是150 x 50.我啟用了sizeClasses (wAny hAny)和AutoLayout 在模擬度量標准中,我設置了Size = FreeformStatus Bar = None ,all other = Inferred

我的自定義UIView類中的代碼如下所示:

#import "CustomView.h"

@implementation CustomView

#pragma mark - Object lifecycle

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];

    if (self) {
        [self setup];
    }

    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];

    if (self) {
        [self setup];
    }

    return self;
}

#pragma mark - Private & helper methods

- (void)setup {
    if (self.subviews.count == 0) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
        self.bounds = self.view.bounds;
        [self addSubview:self.view];
    }
}

@end

在我想要添加這個自定義UIView UIViewController中,我創建了虛擬UIView(我在Interface Builder中設置了它的大小),我想在其中添加我的CustomView我希望我的CustomView適合我的容器視圖的邊界

我想這樣做:

_vCustomView = [[CustomView alloc] init];
_vCustomView.translatesAutoresizingMaskIntoConstraints = NO;
[_vContainer addSubview:_vCustomView];

[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];

但沒有運氣。 假設我的容器視圖是300 x 100,當我向其添加自定義UIView時, 我的自定義視圖仍然是150 x 50

我試圖在沒有容器視圖的情況下工作 - 將我的自定義UIView對象直接添加到我的UIViewController self.view中,並設置它的寬度和高度:

  • autoLayout約束
  • 在初始化我的自定義UIView時使用initWithFrame

但又一次 - 沒有運氣。 自定義視圖始終為150 x 50。

有人可以向我解釋如何以編程方式添加我在XIB制作的自定義UIView並使用autoLayout約束調整大小

提前謝謝了。

編輯#1:我在我的CustomView上運行Andrea的代碼時遇到的錯誤

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x17489b760 V:[UIView:0x17418d820(91)]>",
    "<NSLayoutConstraint:0x170c9bf80 V:|-(0)-[CustomView:0x1741da7c0]   (Names: '|':CustomView:0x1741da8b0 )>",
    "<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-|   (Names: '|':CustomView:0x1741da8b0 )>",
    "<NSLayoutConstraint:0x170c9be90 V:|-(0)-[CustomView:0x1741da8b0]   (Names: '|':UIView:0x17418d820 )>",
    "<NSLayoutConstraint:0x170c9bee0 CustomView:0x1741da8b0.bottom == UIView:0x17418d820.bottom>",
    "<NSAutoresizingMaskLayoutConstraint:0x170c9dba0 h=--& v=--& CustomView:0x1741da7c0.midY == + 25.0>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-|   (Names: '|':CustomView:0x1741da8b0 )>

編輯#2:它有效!

@Andrea補充說:

view.translatesAutoresizingMaskIntoConstraints = NO;

在他的:

- (void) stretchToSuperView:(UIView*) view;

方法,一切都像我預期的那樣。

感謝@Andrea。

我想主要的問題是,當您將xib添加到內容視圖時,不要使用自動布局。
在init方法中添加子視圖后,請調用該方法,傳遞xib的視圖:

- (void) stretchToSuperView:(UIView*) view {
    view.translatesAutoresizingMaskIntoConstraints = NO;
    NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
    NSString *formatTemplate = @"%@:|[view]|";
    for (NSString * axis in @[@"H",@"V"]) {
        NSString * format = [NSString stringWithFormat:formatTemplate,axis];
        NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
        [view.superview addConstraints:constraints];
    }

}

[編輯]
您的設置代碼應如下所示:

- (void)setup {
    if (self.subviews.count == 0) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
        self.bounds = self.view.bounds;
        [self addSubview:self.view];
        [self stretchToSuperView:self.view];
    }
}

注意我在視圖中添加了view.translatesAutoresizingMaskIntoConstraints = NO;
[編輯2]
我會按照要求詳細說明我的答案。 使用autolayout,當您添加視圖而不設置約束時,autolayout會自動將自動調整蒙版轉換為約束,它們的默認屬性是UIViewAutoresizingNone ,這意味着不自動調整大小。
您的XIB視圖已添加到其父級而沒有約束,並且沒有自動大小的可能性,因此保持其原始大小。 由於您希望視圖根據視圖調整大小,因此您有兩種選擇:

  • 將xib視圖的自動調整遮罩更改為靈活的寬度和高度,但它們需要與父級大小匹配,否則您將無法完整覆蓋
  • 添加一些限制兩個視圖的約束,以相應地更改父更改。 你在XIB視圖和它的父視圖之間實現了這個說法,尾隨/前導和頂部/底部之間的空間是0.就像你在他們的邊界上放了一些膠水。 為此,您需要將自動轉換大小調整掩碼設置為NO,否則您可能會在日志中發布一些沖突。

您稍后要做的是將視圖(承載XIB視圖)的約束添加到其超級視圖,但XIB與其父視圖之間沒有約束,因此autolayout不知道如何調整XIB視圖的大小。
視圖層次結構中的每個視圖都應具有自己的約束。
希望這有助於更好地理解。

在你的代碼中你應該有這樣的東西:

首先, IBOutlet的寬度約束你想改變,無論是在的viewController或在您的CustomView (我真的不知道你有邏輯來計算約束值)。

@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint;

然后,在你想要更新常量值的方法中,你會有這樣的事情:

-(void)updateWidth {
    [self.widthConstraint setConstant:newConstant];
    [self.view layoutIfNeeded]; // self.view must be an ancestor of the view

    //If you need the changes animated, call layoutIfNeeded in an animation block
}

希望這對你有用。 祝好運!

Swift 4.0函數可以拉伸到超級視圖:

代碼片段:

static public func stretchToSuperView(view:UIView)
    {
        view.translatesAutoresizingMaskIntoConstraints = false
        var d = Dictionary<String,UIView>()
        d["view"] = view
        for axis in ["H","V"] {
            let format = "\(axis):|[view]|"
            let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(rawValue: 0), metrics: [:], views: d)
            view.superview?.addConstraints(constraints)
        }
    }

注意:只需使用參數作為子視圖調用該函數。

這有助於我解決swift 4.0中的.xib resing問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM