ios - 如何使用自动布局使 Nib View 适合标签的内容

标签 ios objective-c autolayout

我想要一个可扩展其高度的自定义视图(自定义警报视图),以适合其子视图。我发现了类似的问题,但是建议的答案都不能解决我的问题。有什么想法要实现吗?在这种情况下,是否可以使用AutoLayout动态更改 super 视图的高度?

我的笔尖文件看起来像这样...

enter image description here

输出:

enter image description here

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

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;

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

最佳答案

在这里,我花了大约一个小时完成了这个工作,它是专门为这个问题创建的,它的工作原理如下:

[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

首先,对所有“大声笑,但您无法做到,CUZ自动布局不建议使用硬编码的数字,大声笑”,只是不,您不知道您在说什么,而且您没有概念关于自动布局引擎如何工作的信息,因此请随时前进并拖曳另一个Q / A方案。因此,既然这已经不成问题,那么它适用于所有iphone尺寸,而无需做很多事情,而不必更改字体大小(也许)并更改颜色,角半径,字体本身等,等等。甚至可以像Alert View笔尖那样在侧面添加一个漂亮的按钮。永远不要在情节提要和nib文件中执行任何操作的好处是,您可以以相对容易的方式完全控制所有元素。如此说来,这就是逻辑:

我编写此代码时并未使用UIButton作为按钮,因为我不想依赖UIKit提供的任何“一个”特定UI元素,因此,将UIControl子类化,然后粉碎其他UI元素,就可以达到目的,同时允许用户通过向上述元素添加自己的触摸手势或使用类自己的触摸处理程序来使用他们想要的任何UI元素,就像我在这里所做的那样。视图底部的蓝色“按钮”是一个UILabel,其中UIControl的触摸事件被视为“有效”,所有其他触摸事件都将被忽略(请参见触摸事件功能中的逻辑)。实例和初始化程序完全没有必要,我这样做是因为它是我为自己的 private 应用程序构建目的而创建的更大框架的一部分,如果对您没有意义,请忽略它。

它是如何工作的:标签“fakeLabelResizingWindow”是一个UILabel,我使用UILabel是因为可以确保获得调整为文本的大小调整视图的功能,而不必做比在此子类中所做的更多的事情。关于IOS的最好之处在于,您可以根据需要使用元素,以避免噩梦般长的Sub类方法执行与UIKit的另一个UI元素相同的操作。当您可以使UIKit为您完成它而又不需要做更多的事情时,为什么要覆盖drawRect呢?除了将标准元素“引导”到正确的形式以创建一个漂亮的小自定义警报视图之外,还可以进行其他操作。

您会注意到,使用调整大小宏可以调整所有元素的大小,该宏使调整视图成为 super 简单的模式,可为iPhone 6+编程,几乎所有视图都将适应所有iPhone的正确视图,而不会破坏布局约束。这样一来,您基本上就可以通过编程方式完成所有操作,只需1次即可完成所有操作,以适应所有iPhone设备。我没有给出实现此目标的真正方法,该宏只是更大的自定义布局引擎的一小段,但是您明白了。

如您所见,此UIControl的子视图已添加到“fakeLabelResizingWindow”视图,伪标签已添加到UIControl,添加了约束以允许外部“fakeLabelResizingWindow”略微弯曲,但三个附加项的内部胆量标签以更严格的方式约束。有关概念证明,请参见下面的屏幕截图,此屏幕会自动调整大小以适合文本。您必须通过使用“框架”初始化此自定义警报视图来调用该方法,也可以自定义此点,以便对该子类进行单行调用即可更改颜色,字体,字体大小,图层等。 ,这是无限的,但是您需要更改子类的代码,并以IVAR的形式公开更多变量,以将变量公开给整个类体系结构和方法调用,以使其更加“轻松”。

最后但并非最不重要的一点是,这是一个出于很多原因的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

关于ios - 如何使用自动布局使 Nib View 适合标签的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31998403/

相关文章:

ios - 检测是否已从集成应用商店 IOS 下载应用

ios - 连接到 iOS MobileSms 应用程序

objective-c - 为 UINavigationBar 的 barTintColor 设置动画

ios - 如何在 iPhone 6 和 iPhone 6 Plus 上制作 Zoom 模式的应用程序?

ios - 如何向自定义表格 View 单元格 xib 文件添加约束?

ios - 我怎样才能快速洗牌 RLMResults ?

ios - 从 NSDictionary 获取信息

ios - 如何在 UIButton 上设置宽度约束

ios - Apple Pay 与 React Native

android - 实现 Base 64 和 SHA