Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 隐藏视图时,如何使用“自动布局”移动其他视图?_Ios_Iphone_Cocoa Touch_Interface Builder_Autolayout - Fatal编程技术网

Ios 隐藏视图时,如何使用“自动布局”移动其他视图?

Ios 隐藏视图时,如何使用“自动布局”移动其他视图?,ios,iphone,cocoa-touch,interface-builder,autolayout,Ios,Iphone,Cocoa Touch,Interface Builder,Autolayout,我已经在IB中设计了我的自定义单元,将其子类化,并将我的插座连接到我的自定义类。我在单元格内容中有三个子视图,它们是:UIView(cdView)和两个标签(titleLabel和emailLabel)。根据每行可用的数据,有时我希望在单元格中显示UIView和两个标签,有时只显示两个标签。我想做的是这样设置约束,如果我将UIView属性设置为hidden,或者将其从superview中删除,则两个标签将向左移动。我试图为10px将UIView前导约束设置为Superview(单元格内容),为1

我已经在IB中设计了我的自定义单元,将其子类化,并将我的插座连接到我的自定义类。我在单元格内容中有三个子视图,它们是:UIView(cdView)和两个标签(titleLabel和emailLabel)。根据每行可用的数据,有时我希望在单元格中显示UIView和两个标签,有时只显示两个标签。我想做的是这样设置约束,如果我将UIView属性设置为hidden,或者将其从superview中删除,则两个标签将向左移动。我试图为10px将UIView前导约束设置为Superview(单元格内容),为10px将UILabels前导约束设置为下一个视图(UIView)。稍后在我的代码中

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];

if ([record.imageURL is equalToString:@""]) {
     cell.cdView.hidden = YES;
}
我正在隐藏我的cell.cdView,我希望标签移到左侧,但它们在cell中的位置不变。我试图从superview中删除cell.cdView,但也没有成功。我附上图片,以澄清我的想法

我知道如何通过编程来实现这一点,我并不寻求解决方案。我想要的是在IB中设置约束,我希望如果删除或隐藏其他视图,我的子视图将动态移动。在IB中使用自动布局可以做到这一点吗

.....

这是可能的,但你得做一些额外的工作。首先有两个概念上的问题需要解决:

  • 隐藏视图,即使不绘制,仍参与自动布局,并且通常保留其框架,将其他相关视图保留在其位置
  • 从超级视图中删除视图时,所有相关约束也将从该视图层次中删除
在您的情况下,这可能意味着:

  • 如果将左视图设置为隐藏,则标签将保持在位,因为该左视图仍在占用空间(即使不可见)
  • 如果删除左视图,标签可能会受到模糊约束,因为标签的左边缘不再具有约束
您需要做的是明智地过度约束标签。保留现有约束(与其他视图的间距为10pts),但添加另一个约束:使标签的左边缘与superview的左边缘的间距为10pts,且具有非必需的优先级(默认的高优先级可能会很好地工作)

然后,当您希望它们向左移动时,请完全删除左视图。左视图的强制10pt约束将随其相关的视图一起消失,并且您将只剩下一个高优先级约束,即标签距离其超级视图10pt。在下一个布局过程中,这将导致它们向左扩展,直到它们填充superview的宽度,但边缘周围的间距除外


一个重要的警告:如果您想要将左视图重新添加到图片中,不仅需要将其添加回视图层次结构中,还必须同时重新建立其所有约束。这意味着每当视图再次显示时,您需要一种方法将视图与其标签之间的10pt间距约束放回原处。

将uiview和标签之间的约束连接为IBOutlet,并在set hidden=YES时将优先级成员设置为较小的值。

在运行时添加或删除约束是一项重量级操作,可以影响性能。然而,有一个更简单的选择

对于要隐藏的视图,设置宽度约束。将具有前导水平间隙的其他视图约束到该视图

要隐藏,请将宽度约束的
.constant
更新为0.f。其他视图将自动向左移动到假定位置

有关更多详细信息,请参见我的其他答案:

对于谷歌人来说:基于Max的答案,为了解决许多人注意到的填充问题,我只是增加了标签的高度,并将该高度用作分隔符,而不是实际的填充。这个想法可以扩展到包含视图的任何场景

下面是一个简单的例子:


在本例中,我将作者标签的高度映射到适当的
IBOutlet

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

当我将约束的高度设置为
0.0f
时,我们保留了“填充”,因为播放按钮的高度允许它。

我最后做的是创建2个XIB。一个有左视图,一个没有左视图。我在控制器中注册了两者,然后决定在cellForRowAtIndexPath期间使用哪一个

cell.authorLabelHeight.constant = 0;
它们使用相同的UITableViewCell类。缺点是XIB之间的内容有些重复,但这些单元格非常基本。好处是我没有一堆代码来手动管理删除视图、更新约束等

一般来说,这可能是一个更好的解决方案,因为它们在技术上是不同的布局,因此应该有不同的XIB

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];

正如no_场景所建议的,您完全可以通过在运行时更改约束的优先级来实现这一点。这对我来说容易得多,因为我有不止一个必须删除的阻塞视图

下面是使用ReactiveCocoa的一个片段:

RACSignal* isViewOneHiddenSignal = RACObserve(self.viewModel, isViewOneHidden);
RACSignal* isViewTwoHiddenSignal = RACObserve(self.viewModel, isViewTwoHidden);
RACSignal* isViewThreeHiddenSignal = RACObserve(self.viewModel, isViewThreeHidden);
RAC(self.viewOne, hidden) = isViewOneHiddenSignal;
RAC(self.viewTwo, hidden) = isViewTwoHiddenSignal;
RAC(self.viewThree, hidden) = isViewThreeHiddenSignal;

RAC(self.viewFourBottomConstraint, priority) = [[[[RACSignal
    combineLatest:@[isViewOneHiddenSignal,
                    isViewTwoHiddenSignal,
                    isViewThreeHiddenSignal]]
    and]
    distinctUntilChanged]
    map:^id(NSNumber* allAreHidden) {
        return [allAreHidden boolValue] ? @(780) : @(UILayoutPriorityDefaultHigh);
    }];

RACSignal* updateFramesSignal = [RACObserve(self.viewFourBottomConstraint, priority) distinctUntilChanged];
[updateFramesSignal
    subscribeNext:^(id x) {
        @strongify(self);
        [self.view setNeedsUpdateConstraints];
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];
        }];
    }];

我的项目使用了一个自定义的
@IBDesignable
子类
UILabel
(以确保颜色、字体、插图等的一致性),我实现了如下功能:

override func intrinsicContentSize() -> CGSize {
    if hidden {
        return CGSizeZero
    } else {
        return super.intrinsicContentSize()
    }
}

这允许label子类参与自动布局,但隐藏时不占用空间。

如果这对某人有帮助,我为使用约束构建了一个helper类。我正在我当前的应用程序中使用它

它可能有点适合我的需要,但您可能会发现它很有用,或者您可能想修改它并创建自己的助手


我必须感谢Tim的,这个,还有这个。

对于那些只支持iOS 8+
的人,有一个新的布尔属性。会的
@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;
cell.authorLabelHeight.constant = 0;
UIView.animateWithDuration(1.0) { () -> Void in
   self.mySubview.hidden = !self.mySubview.hidden
}
    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *viewOne;
@property (strong, nonatomic) IBOutlet UIView *viewTwo;
@property (strong, nonatomic) IBOutlet UIView *viewThree;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewOneWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewTwoWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewThreeWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewBottomWidth;
@end
 #import "ViewController.h"
 @interface ViewController ()
{
  CGFloat viewOneWidthConstant;
  CGFloat viewTwoWidthConstant;
  CGFloat viewThreeWidthConstant;
  CGFloat viewBottomWidthConstant;
}
@end

@implementation ViewController
@synthesize viewOne, viewTwo, viewThree;

- (void)viewDidLoad {
  [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a 
  nib.

  /*
   0  0   0
   0  0   1
   0  1   0
   0  1   1
   1  0   0
   1  0   1
   1  1   0
   1  1   1
   */

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:YES];


  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

 //    [viewOne setHidden:YES];
 //    [viewTwo setHidden:YES];
 //    [viewThree setHidden:NO];

//    [viewOne setHidden:YES];
//    [viewTwo setHidden:YES];
//    [viewThree setHidden:YES];

 [self hideShowBottomBar];
  }

- (void)hideShowBottomBar
{
  BOOL isOne = !viewOne.isHidden;
  BOOL isTwo = !viewTwo.isHidden;
  BOOL isThree = !viewThree.isHidden;

  viewOneWidthConstant = _viewOneWidth.constant;
  viewTwoWidthConstant = _viewTwoWidth.constant;
  viewThreeWidthConstant = _viewThreeWidth.constant;
  viewBottomWidthConstant = _viewBottomWidth.constant;

   if (isOne && isTwo && isThree) {
    // 0    0   0
    _viewOneWidth.constant = viewBottomWidthConstant / 3;
    _viewTwoWidth.constant = viewBottomWidthConstant / 3;
    _viewThreeWidth.constant = viewBottomWidthConstant / 3;
    }
    else if (isOne && isTwo && !isThree) {
     // 0    0   1
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = 0;
    }
   else if (isOne && !isTwo && isThree) {
    // 0    1   0
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
    }
    else if (isOne && !isTwo && !isThree) {
    // 0    1   1
    _viewOneWidth.constant = viewBottomWidthConstant;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && isTwo && isThree) {
    // 1    0   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
   }
   else if (!isOne && isTwo && !isThree) {
    // 1    0   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && !isTwo && isThree) {
    // 1    1   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant;
   }
   else if (isOne && isTwo && isThree) {
    // 1    1   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
  }

 - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
 }
 @end
        StackFullView.layer.isHidden = true
        Task_TopSpaceSections.constant = 0.   //your constraint of top view
@IBOutlet var avatar:UIImage!
@IBOutlet var avatarLeadHid:NSLayoutConstraint!

func hideAvatar() {
  self.avatar.isHidden = true
  self.avatarLeadHid.isActive = true
}

func showAvatar() {
  self.avatar.isHidden = false
  self.avatarLeadHid.isActive = false
}