【问题标题】:Autolayout issue for width equally in iOS iPhoneiOS iPhone中宽度相等的自动布局问题
【发布时间】:2015-09-10 04:49:44
【问题描述】:

我有三个视图作为子视图,如下所示,等宽和高度约束

如果视图 B 没有数据,那么它应该如下所示

我的尝试如果 iset B 的宽度为零,那么所有视图的宽度都将为零。

如何获得?

谢谢

【问题讨论】:

  • 是视图 B 可能没有数据的唯一一个,还是可能发生在 3 个视图中的任何一个上?还有可能2个视图没有数据吗?
  • 你的目标 iOS 是什么?是 iOS 8.0 还是更早的版本?
  • @robmayoff iOS 7 和 iOS 8,但如果这仅适用于 iOS 8,您也可以给我答案。
  • @pteofil,是的,你是对的。应满足所有条件。

标签: ios iphone xcode storyboard autolayout


【解决方案1】:

你能做的是给它添加一个宽度约束(中间一个),并使其小于 2000,优先级(1000)大于等于宽度(750)

现在制作一个出口,并且约束条件(

您可以找到sample here

为什么我设置2000 是因为这个约束只需要将宽度归零。如果宽度不为零,它不应该影响宽度。现在由于宽度相等(中间视图)并且它应该小于2000,因此视图在屏幕上显示相同。当我将宽度约束设置为零时,中间视图的宽度变为零,因为它的优先级高于相等的宽度。


此代码将中间视图的宽度设置为零。

- (IBAction)btnClick:(id)sender {
  self.widthView2.constant = 0;
}

输出:

【讨论】:

  • 是的,这很棒但是我是否也应该为其他视图使用相同的登录名?如果只有视图 A 有数据怎么办?
  • 您可以对所有视图使用相同的逻辑,为所有视图创建宽度约束并将其设为零,就像中间的一样
  • 如果只有视图 A 有数据怎么办?
  • 请多解释一下,我没听懂。您只想显示视图 A 吗?
  • 正如我之前所说,只需为所有视图创建约束,就像我为中间视图所做的那样,并将视图 B 和 C 的常量设置为零。如果出现以下情况,我将更新示例的链接你做不到。
【解决方案2】:

下载代码:根据您的要求设置约束。 Click to Download

ViewAViewC 之间的距离创建NSLayoutConstraint _distance_ViewA_ViewC 变量

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //when viewB is hidden remove the comments
    _distance_ViewA_ViewC.constant = 8.0f;
    _viewB.hidden = true;

}

输出

对于viewA, viewB, viewC


对于viewA, ViewCviewB隐藏

【讨论】:

    【解决方案3】:

    首先,确保您的等宽约束设置如下:

    A.width == B.width
    A.width == C.width
    

    不是这样的:

    A.width == B.width
    C.width == B.width
    

    也就是说,确保视图B只涉及一个等宽约束。

    接下来,将出口连接到视图 B 和视图 B 上的等宽约束。

    @property (nonatomic, strong) IBOutlet UIView *viewB;
    @property (nonatomic, strong) IBOutlet NSLayoutConstraint *bEqualWidthConstraint;
    

    要连接约束出口,您需要在情节提要大纲中找到约束。这将是对 A 和 B 最近共同祖先的约束之一;它不会直接在 A 或 B 上。当您在故事板大纲中找到它时,您可以从它控制拖动到源代码中的插座(或者您可以通过控制拖动到@interface 中的任何位置来创建一个新插座)。

    添加另一个属性来保持另一个约束,将 B 的宽度设置为零:

    @property (nonatomic, strong) NSLayoutConstraint *bZeroWidthConstraint;
    

    初始化bZeroWidthConstraint但不要安装它:

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.bZeroWidthConstraint = [NSLayoutConstraint
            constraintWithItem:self.viewB attribute:NSLayoutAttributeWidth
            relatedBy:NSLayoutRelationEqual
            toItem:nil attribute:NSLayoutAttributeNotAnAttribute
            multiplier:0 constant:0];
    }
    

    当你想隐藏视图B时,卸载bEqualWidthConstraint并安装bZeroWidthConstraint

    在 iOS 8.0 上,您可以通过将其 active 属性设置为 NO 来卸载约束,但在早期版本中,您必须向安装了约束的视图发送消息。这通常是受约束视图的最近共同祖先。假设A和B的共同祖先是viewB.superview

    - (void)hideB {
        [self.viewB.superview removeConstraint:self.bEqualWidthConstraint];
        [self.viewB addConstraint:self.bZeroWidthConstraint];
    }
    

    注意,由于bZeroWidthConstraint只约束视图B,所以可以直接安装在视图B上。

    当你想再次显示视图B时,卸载bZeroWidthConstraint并重新安装bEqualWidthConstraint

    - (void)showB {
        [self.viewB removeConstraint:self.bZeroWidthConstraint];
        [self.viewB.superview addConstraint:self.bEqualWidthConstraint];
    }
    

    【讨论】:

    • 它很棒而且效果很好,但我应该对其他人也使用相同的逻辑吗?
    【解决方案4】:

    首先,您需要了解您可以在 iOS 中为不同的约束设置优先级。默认优先级为 1000,最高。

    现在,您需要将 equalWidth 约束的优先级设置为 750。其次,您需要将水平间距从 ViewA 应用到 ViewB,并将 ViewB 应用到 ViewC。理想情况下,水平间距的常数应为 0,这将使三个视图的边粘在一起。

    现在,当您将 ViewB 的宽度设置为 0 时,您的 ViewA 和 ViewC 将占据所有空间,宽度相等,而 ViewB 将消失。

    如果您对此有任何困惑,请告诉我。

    【讨论】:

    • 感谢您的回答,但我应该隐藏View B.hidden = YES 还是将宽度常量设置为零?
    • 您需要将 ViewB 的宽度常数设置为 0。此外,您还需要在 ViewA 和 ViewC 之间为 equalWidth 增加一个约束,优先级为 750。
    • 不工作,因为我设置了 ViewA、View B 和 View C 等宽是 1000 的优先级
    • 然后您必须将优先级更改为 750。优先级为 1000 时它无法正常工作,因为约束冲突会导致结果模棱两可。
    猜你喜欢
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多