Отображение и скрытие представлений при использовании AutoLayout

У меня есть несколько представлений, в которых я должен удалить UIView и позволить всем другим представлениям перестроиться без этого представления. Обычно я делаю это, создавая несколько ограничений с разными весами, поэтому, когда я удаляюFromSuperView, все остальные ограничения с меньшим весом начинают работать, и все переставляется так, как я хочу.

Он работает отлично, но теперь мне нужно показывать и скрывать представление, но когда я удаляюFromSuperView, это представление исчезает со всеми его ограничениями... Я понятия не имею, что делать... Я могу изменить ограничения ширины и высоты на ноль для вид, который я хочу скрыть... но проблема в том, что тогда мне нужно жестко закодировать высоту в коде, и мне это не нравится...

Каков наилучший способ скрыть и показать UIViews? Что-то вроде свойства "Установлено", которое можно задать в ИБ, но из кода.


person Andres    schedule 19.11.2015    source источник


Ответы (4)


Когда вы удаляете представление из суперпредставления, вы теряете ограничение, вы в основном делаете его доступным для любого объекта в своем представлении, и таким образом вам нужно написать некоторые методы для добавления к другим представлениям (с программным добавлением ограничения) или удалить его снова .

По моему опыту, чтобы скрыть вид, вы можете использовать анимацию ограничений или анимацию самого вида и сбрасывать ее влево, вправо, вверх или вниз. Кроме того, чтобы он был недоступен при взаимодействии с пользователем, вы можете просто отключить его с помощью self.view.hidden = true или self.view.userInteractionEnabled = false. используйте dispatch_async(), когда вы также обновляете представление, Apple любит людей, которые кодируют стандарт :).

Скрыть вид с анимацией:

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.view.hidden = true // Or userInteractionEnable = false
                UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
                    self.reportView.alpha = 0
                    }, completion: nil)
            })

Скрыть вид с ограничением:

Вам нужно создать ограничение IBOutlet, чтобы использовать константу с анимацией.

        self.someView.constant = -205 // Throw it off canaves
        UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
            self.view.layoutIfNeeded()
            }, completion: { (finished: Bool)-> Void in
                self.someView.hidden = true
        })

Чтобы это появилось, просто сделайте то же самое, подумайте в обратном порядке. но не removeFromSuperView(), если только вы не пытаетесь прикрепить его к программе быстрого реагирования или чему-то в этом роде.

person Brian Nezhad    schedule 19.11.2015

Если вы нацелены на iOS 9 и выше, вы можете попробовать UIStackView.

Один из способов сохранить ограничения — создать категорию в UIView.

@interface UIView (ConstraintsPreserving)

@property (nonatomic, strong) NSMutableArray * preservedConstraints;

-(void)removeFromSuperViewPreservingConstriants;
-(void)addToSuperViewPreservingConstriants:(UIView *)superView;

@end

#import <objc/runtime.h>

@implementation UIView (ConstraintsPreserving)

@dynamic preservedConstraints;

-(void)setPreservedConstraints:(NSMutableArray *)object {
    objc_setAssociatedObject(self, @selector(preservedConstraints), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSMutableArray *)preservedConstraints {
    return objc_getAssociatedObject(self, @selector(preservedConstraints));
}

-(void)removeFromSuperViewPreservingConstriants
{
    if(!self.superview) return;

    self.preservedConstraints = [NSMutableArray new];
    [self.preservedConstraints addObjectsFromArray:[self constraints]];

    for (NSLayoutConstraint * constraint in self.superview.constraints) {
        if([constraint.firstItem isEqual:self] || [constraint.secondItem isEqual:self])
            [self.preservedConstraints addObject:constraint];
    }
    [self removeFromSuperview];
}

-(void)addToSuperViewPreservingConstriants:(UIView *)superView
{
    if(self.superview) return;

    [superView addSubview:self];
    [superView addConstraints:self.preservedConstraints];
    self.preservedConstraints = nil;
}

@end

PS: Это строго фиксирует ограничения, фиксируя все представления, связанные с этими ограничениями.

person BangOperator    schedule 20.11.2015

Я не уверен, что это подходит для вашей проблемы, но пару раз я делал это для того, чтобы убедиться, что представление, которое вы хотите скрыть, находится в контейнере. Такой контейнер должен иметь ограничение по высоте и ширине (и это вам может не понравиться). Затем вы создаете IBOutlets для каждого из этих ограничений в соответствующем контроллере представления (управление перетаскиванием из ограничения в раскадровке). Наконец, вы можете сохранить начальное значение ограничения в viedidload, чтобы использовать его позже для переключения с нуля на это значение, каким бы оно ни было.

person Eppilo    schedule 19.11.2015
comment
проблема с этим заключается в том, что у вас есть представления, которые растут в зависимости от содержимого представления... Я не могу жестко закодировать значение :( - person Andres; 19.11.2015
comment
Сложная ситуация без кода. Как насчет того, чтобы добавить низкоприоритетное ограничение на высоту и ширину, чтобы они были очень большими (за пределами экрана), и обнулить их, когда ваше представление должно исчезнуть? - person Eppilo; 19.11.2015

Итак, я закончил создание IBOutlets для представлений, которые я хочу скрыть. Я установил ограничения ширины и высоты на ноль, чтобы скрыть вид. Также я установил несколько IBOutlets и изменил приоритет этих ограничений, чтобы я мог переупорядочить вещи...

Это лучший способ, который я нашел для этого.

person Andres    schedule 26.11.2015