如何使用AutoLayout

时间:2015-08-13 21:04:42

标签: ios objective-c autolayout

我想要一个扩展其高度的自定义视图(自定义警报视图),以便正确地适应其子视图。我发现了类似的问题,但没有一个建议的答案解决了我的问题。任何想法如何实现?在这种情况下,是否可以使用AutoLayout动态更改superview的高度?

我的nib文件看起来像这样......

enter image description here

输出

enter image description here

通过将红色 - 蓝色底部约束的优先级更改为Lowcontainer遵循标签的大小,但超级视图仍然相同。

enter image description here

layoutIfNeeded无效,当我覆盖translatesAutoresizingMaskIntoConstraints时,UILabel未正确包装其内容。

enter image description here

修改

这就是我现在所拥有的,以实现我的目标:

设置UILabel的文字后,

[redView layoutIfNeeded];
CGRect frame = redView.frame;
frame.size.height = 2 * padding + CGRectGetMaxY(greyLabel.frame);
redView.frame = frame;

这样我可以调整笔尖的高度以匹配当前标签的高度。

3 个答案:

答案 0 :(得分:0)

好的,你希望你的细胞高度是动态的,以适应标签吗?这是我的方法。您也可以查看本教程self-sizing-cell

this is my constrains for the label

viewDidLoad方法中,添加以下代码:

self.tableView.estimatedRowHeight = 83.0f; 
self.tableView.rowHeight = UITableViewAutomaticDimension;

并在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath中配置标签:

cell.questionBodyLabel.numberOfLines = 0;
cell.questionBodyLabel.lineBreakMode = NSLineBreakByWordWrapping;
[cell.questionBodyLabel sizeToFit];
cell.questionBodyLabel.text = someLongText;

你很高兴。不要忘记删除heightForRowAtIndexPath方法,否则它将无效。

答案 1 :(得分:0)

在这里,我在大约一个小时内创建它,它是为这个问题而创建的,它的工作原理如下:

[self.view addSubview:[CCHSCustomAlertView customAlertViewWithTextBody:tt title:@"This is an Alert!" andFrame:self.view.frame]];

这是代码,试一试:

#import <UIKit/UIKit.h>

@interface CCHSCustomAlertView : UIControl

- (id)initWithTextString:(NSString*)string title:(NSString*)title andFrame:(CGRect)frame  NS_DESIGNATED_INITIALIZER;
+ (instancetype)customAlertViewWithTextBody:(NSString *)text title:(NSString*)title andFrame:(CGRect)frame;

@end

实施档案:

#import "CCHSCustomAlertView.h"

#define SCREEN_WIDTH ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)

#define SCREEN_HEIGHT ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)

#define MAX_SCREEN_HEIGHT_IS_IPHONE6_PLUS 736.00
#define MAX_SCREEN_WIDTH_IS_IPHONE6_PLUS 414.00

#define heightResizer(n) n/MAX_SCREEN_HEIGHT_IS_IPHONE6_PLUS*SCREEN_HEIGHT
#define widthResizer(n) n/MAX_SCREEN_WIDTH_IS_IPHONE6_PLUS*SCREEN_WIDTH

@interface CCHSCustomAlertView ()
@end

@implementation CCHSCustomAlertView {
    UILabel * dismissAlertViewButton;
    UILabel * fakeLabelResizingWindow;
    UIView * fadedBackgroundView;
}

- (instancetype)initWithText:(NSString *)text title:(NSString*)title andFrame:(CGRect)frame {
    return [self initWithTextString:text title:title andFrame:frame];
}

+ (instancetype)customAlertViewWithTextBody:(NSString *)text title:(NSString*)title andFrame:(CGRect)frame {
    return [[self alloc] initWithTextString:text title:title andFrame:frame];
}

- (id)initWithFrame:(CGRect)frame {
    return [self initWithTextString:nil title:nil andFrame:CGRectZero];
}

- (id)initWithTextString:(NSString*)string title:(NSString*)title andFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {

        fadedBackgroundView = [UIView new];
        [fadedBackgroundView setFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        [fadedBackgroundView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:0.4]];
        [fadedBackgroundView setAlpha:0];
        [self addSubview:fadedBackgroundView];

        fakeLabelResizingWindow = [UILabel new];
        [fakeLabelResizingWindow setTranslatesAutoresizingMaskIntoConstraints:false];
        [fakeLabelResizingWindow setFont:[UIFont systemFontOfSize:heightResizer(15)]];
        [fakeLabelResizingWindow setTextColor:[UIColor clearColor]];
        [fakeLabelResizingWindow setNumberOfLines:0];
        [fakeLabelResizingWindow setText:string];
        [fakeLabelResizingWindow setClipsToBounds:true];
        [[fakeLabelResizingWindow layer] setCornerRadius:3];
        [fakeLabelResizingWindow setBackgroundColor:[UIColor whiteColor]];
        [fakeLabelResizingWindow setLineBreakMode:NSLineBreakByCharWrapping];
        [self addSubview:fakeLabelResizingWindow];

        UILabel * header = [UILabel new];
        [header setTranslatesAutoresizingMaskIntoConstraints:false];
        [header setTextAlignment:NSTextAlignmentCenter];
        [header setFont:[UIFont boldSystemFontOfSize:heightResizer(20.0)]];
        [header setText:title];
        [header setTextColor:[UIColor darkGrayColor]];
        [fakeLabelResizingWindow addSubview:header];

        UILabel * header1 = [UILabel new];
        [header1 setTranslatesAutoresizingMaskIntoConstraints:false];
        [header1 setTextAlignment:NSTextAlignmentCenter];
        [header1 setFont:[UIFont systemFontOfSize:heightResizer(15)]];
        [header1 setNumberOfLines:0];
        [header1 setText:string];
        [header1 setTextColor:[UIColor darkGrayColor]];
        [fakeLabelResizingWindow addSubview:header1];

        dismissAlertViewButton = [UILabel new];
        [[dismissAlertViewButton layer] setCornerRadius:3];
        [dismissAlertViewButton setTranslatesAutoresizingMaskIntoConstraints:FALSE];
        [dismissAlertViewButton setText:@"Got It"];
        [dismissAlertViewButton setTextAlignment:NSTextAlignmentCenter];
        [dismissAlertViewButton setTextColor:[UIColor whiteColor]];
        [dismissAlertViewButton setFont:[UIFont systemFontOfSize:heightResizer(15)]];
        [dismissAlertViewButton setBackgroundColor:[UIColor blueColor]];
        [fakeLabelResizingWindow addSubview:dismissAlertViewButton];

        NSDictionary * views = NSDictionaryOfVariableBindings(header1, header, dismissAlertViewButton);
        NSDictionary * metrics = @{@"superViewHorizontalMarginOffset" : @(widthResizer(15.0)),
                                   @"buttonHeight" : @(heightResizer(44.0)),
                                   @"superViewVertMargOffset" : @(heightResizer(15.0))};

        [fakeLabelResizingWindow addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-superViewHorizontalMarginOffset-[header]-superViewHorizontalMarginOffset-|"
                                                                                        options:0
                                                                                        metrics:metrics
                                                                                          views:views]];

        [fakeLabelResizingWindow addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-superViewHorizontalMarginOffset-[header1]-superViewHorizontalMarginOffset-|"
                                                                                        options:0
                                                                                        metrics:metrics
                                                                                          views:views]];

        [fakeLabelResizingWindow addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-superViewHorizontalMarginOffset-[dismissAlertViewButton]-superViewHorizontalMarginOffset-|"
                                                                                        options:0
                                                                                        metrics:metrics
                                                                                          views:views]];

        [fakeLabelResizingWindow addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-superViewVertMargOffset-[header]-superViewVertMargOffset-[header1]-superViewVertMargOffset-[dismissAlertViewButton(buttonHeight)]-superViewVertMargOffset-|"
                                                                                        options:0
                                                                                        metrics:metrics
                                                                                          views:views]];

        [self addConstraint:[NSLayoutConstraint constraintWithItem:fakeLabelResizingWindow
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:nil
                                                         attribute:NSLayoutAttributeNotAnAttribute
                                                        multiplier:1.f
                                                          constant:SCREEN_WIDTH-widthResizer(60)]];

        [self addConstraint:[NSLayoutConstraint constraintWithItem:fakeLabelResizingWindow
                                                         attribute:NSLayoutAttributeCenterX
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:self
                                                         attribute:NSLayoutAttributeCenterX
                                                        multiplier:1.f
                                                          constant:0]];

        [self addConstraint:[NSLayoutConstraint constraintWithItem:fakeLabelResizingWindow
                                                         attribute:NSLayoutAttributeCenterY
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:self
                                                         attribute:NSLayoutAttributeCenterY
                                                        multiplier:1.f
                                                          constant:0]];

        [fakeLabelResizingWindow setTransform:CGAffineTransformMakeTranslation(0, SCREEN_HEIGHT)];

        [UIView animateWithDuration:0.5 animations:^{
            [fadedBackgroundView setAlpha:1];
            [fakeLabelResizingWindow setTransform:CGAffineTransformIdentity];
        }];
    }
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if ((CGRectContainsPoint([self frame], [[touches anyObject] locationInView:dismissAlertViewButton]))) {
        [dismissAlertViewButton setBackgroundColor:[UIColor lightGrayColor]];
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if ((CGRectContainsPoint([self frame], [[touches anyObject] locationInView:dismissAlertViewButton]))) {
        [dismissAlertViewButton setBackgroundColor:[UIColor blueColor]];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    if ((CGRectContainsPoint([self frame], [[touches anyObject] locationInView:dismissAlertViewButton]))) {
        [dismissAlertViewButton setBackgroundColor:[UIColor blueColor]];
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [dismissAlertViewButton setBackgroundColor:[UIColor blueColor]];
    if ((CGRectContainsPoint([self frame], [[touches anyObject] locationInView:dismissAlertViewButton]))) {
        [UIView animateWithDuration:0.5 animations:^{
            [fakeLabelResizingWindow setTransform:CGAffineTransformMakeTranslation(0, SCREEN_HEIGHT)];
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.1 animations:^{
                [fadedBackgroundView setAlpha:0];
            } completion:^(BOOL finished) {
                [self removeFromSuperview];
            }];
        }];
    }
    [self sendActionsForControlEvents:UIControlEventTouchUpInside];
}

    @end

首先,关闭所有&#34; LOLZ,但是你可以做CUZ汽车布局是否需要拥有硬编码的数字LOLZ&#34;,就是不要,你不知道你在说什么,你不知道自动布局引擎是如何工作的,所以请随意移动并转向另一个Q / A场景。所以,现在这已经不再适用了,对于所有iphone尺寸而言,这不仅可以改变字体大小(可能),还可以改变颜色,角半径,字体本身等等。甚至可以像警报视图笔尖一样在侧面添加一个漂亮的按钮。从不在故事板和nib文件中做任何事情的好处是,您可以以相对简单的方式完全控制所有元素。所以,说到这里,逻辑是:

我没有使用按钮的UIButton编码,因为我不想依赖任何&#34;一个&#34;由UIKit提供的特定UI元素,因此,继承UIControl然后粉碎其他UI元素的同时允许用户通过向所述元素添加他们自己的触摸手势或使用类自己的触摸处理程序来使用他们想要的任何UI元素。我在这里干嘛蓝色&#34;按钮&#34;在视图的底部是UILabel,其中UIControl的触摸事件被认为是&#34;有效&#34;,所有其他触摸事件被忽略(参见触摸事件功能中的逻辑)。实例和初始化程序根本不是必需的,我之所以这样做,是因为它是我为自己的私有应用程序构建目的而创建的更大框架的一部分,如果它没有这样做的话。对你有意义,然后忽略它。

这是如何工作的:标签&#34; fakeLabelResizingWindow&#34;是UILabel,我使用的是UILabel,因为我保证能够获得调整文本的大小调整视图的功能,而不必像我在这个子类中所做的那样做更多。关于IOS的最好的部分是你可以使用你想要的元素,以避免噩梦般长的Sub类方法与UIKit的另一个UI元素做同样的事情。为什么在你可以让UIKit为你做的时候覆盖drawRect而不需要做更多的事情而不需要做更多的事情&#34;指南&#34;将标准元素转化为正确的格式,创建一个漂亮的小自定义警报视图。

您会注意到所有元素都使用调整大小宏进行调整大小,这样可以调整视图的超级简单模式,iPhone 6+的程序和几乎所有视图都会重新调整所有iPhone的正确视图,而不会破坏布局对抗。这允许您以编程方式执行所有操作,基本上只需一次,所有内容都可以通过,以适应所有iPhone设备。我没有给出实现此方法的真实方法,这个宏只是一个更大的自定义布局引擎的小片段,但你明白了。

此UIControl的子视图被添加到&#34; fakeLabelResizingWindow&#34;如你所见,伪标签被添加到UIControl,添加约束以允许外部&#34; fakeLabelResizingWindow&#34;稍微弯曲,但三个附加标签的内部胆量受到更严格的限制时尚。请参阅下面的屏幕截图以获取概念验证,此自动调整大小以适合文本。您必须通过使用&#34; frame&#34;来启动此自定义警报视图来调用该方法,您还可以将其自定义为对此子类的单行调用允许您更改颜色,字体,字体大小,层等等,天空是极限,但你需要改变子类的代码并将更多变量暴露为IVAR,以便将变量暴露给整个类体系结构和方法调用,并且为了使这更多&#34;时髦&#34;。

最后但并非最不重要的是,这是一个很多原因的UIControl,我不会为了我的目的而单独说明原因,但是继承UIControls可以做出一些非常好的事情和好时光。你的应用。

做好工作,玩得开心,保持安全,远离笔尖和故事板。

概念证明:

This is large alert view with a terrible wall of text

This is large alert view with a terrible wall of text

This is a smaller alert view with terrible text as well

This is a smaller alert view with terrible text as well

答案 2 :(得分:0)

我知道这个问题很旧,但是我有同样的问题。

我想从笔尖加载视图(笔尖内部的所有视图都有适当的约束),设置宽度以适合屏幕,并让高度根据内容进行调整。

解决方案是这样的:

override func didMoveToSuperview() {

    var fitSize = UIView.layoutFittingCompressedSize

    // this is the exact width that I want
    fitSize.width = UIScreen.main.bounds.width

    let size = systemLayoutSizeFitting(fitSize,
                                       withHorizontalFittingPriority: UILayoutPriority.defaultHigh,
                                       verticalFittingPriority: UILayoutPriority.fittingSizeLevel)

    // if you set horizontal priority to UILayoutPriority.fittingSizeLevel, it will set the view size to fit the content, not the screen width

    frame.size = size
}