2015-08-08 2 views
0

Я пытаюсь создать настраиваемое представление, которое отображается точно так же, как клавиатура, но я не могу понять, как использовать манипуляции с фреймами и/или программную автоматическую компоновку для решения моей проблемы.Добавить subview, прикрепленный к нижней части супервизора (пользовательская клавиатура)

В некотором контексте: у меня есть диспетчер представления стиля приложения для обмена сообщениями с текстовым надзором и кнопка, закрепленная в нижней части экрана. Все представления завернуты в прекрасный вид с одним контентом с автозапуском, таким образом, что при появлении клавиатуры он выдвигает весь вид вверх, и когда он исчезает, он отбрасывает весь вид назад. Это поведение, которое я пытаюсь воспроизвести.

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

StickersCollectionViewController *stickerController = [self.storyboard instantiateViewControllerWithIdentifier:@"StickersCollectionViewController"]; 

[self addChildViewController:stickerController]; 
[self.view addSubview:stickerController.view]; 
[stickerController didMoveToParentViewController:self]; 

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:stickerController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.view.bounds.size.height]; 
[self.view addConstraint:constraint]; 

NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:stickerController.view attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual toItem:self.view 
          attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]; 

NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:stickerController.view 
                attribute:NSLayoutAttributeHeight 
                relatedBy:NSLayoutRelationEqual 
                 toItem:nil 
                attribute:NSLayoutAttributeNotAnAttribute 
                multiplier:1.0 
                constant:240.0]; 

[self.view addConstraint:width]; 
[self.view addConstraint:height]; 


double delayInSeconds = 0.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    constraint.constant = 240.0; 
    [UIView animateWithDuration:0.3 
        animations:^{ 
         [self.view layoutIfNeeded]; 
        }]; 
}); 

До сих пор, это выглядит великолепно: вид конкретизируется и добавил в непосредственной близости от экрана, а затем оживляет в поле зрения. Тем не менее, мне также хотелось бы, чтобы мой контроль (упомянутый выше) также оживился с этой точки зрения. Это часть, в которой мне нужна помощь.

Может ли кто-нибудь предложить помощь в этом направлении? Или предложить предложение относительно другого маршрута, на который я мог бы пойти? Благодарю.

ответ

0

Попробуйте это вместо этого, разница использует «[self.view layoutIfNeeded];» как до анимации, так и после анимации, а затем поместив этот «constraint.constant = 240.0;» в анимации.

double delayInSeconds = 0.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [self.view layoutIfNeeded]; 
     [UIView animateWithDuration:0.3 
         animations:^{ 
          constraint.constant = 240.0; 
          [self.view layoutIfNeeded]; 
         }]; 
    }); 

Итак, попробуйте это так:

это:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:stickerController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.view.bounds.size.height]; 

Шоуда, вероятно, это:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:stickerController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 

, потому что вы сдерживая к верхней части представления и не ограничиваясь вершиной представления + self.view.bounds.size.height, не уверен, что это помогает, но это одна идея.

Второе возможное решение - это объединение всех элементов пользовательского интерфейса в UIView и установка этого UIView как вида stickerController.view, это не так прямолинейно, потому что технически вы должны назначить это представление как представление stickerController .view в способе представления нагрузки в impelemntation файле stickerController, а затем приведение типа в stickerController.view, как это, например

Typcasting в файле реализации stickerController

- (void)loadView 
{ 
    [self setView:[ContainerViewThatHasSubViews new]]; 
} 

- (ContainerViewThatHasSubViews*)contentView 
{ 
    return (id)[self view]; 
} 

затем, создать подкласс ContainerViewThatHasSubViews как так

ContainerViewThatHasSubViews.h

@interface ContainerViewThatHasSubViews : UIView 
@property (nonatomic) UIView *subContainerOfContainerViewThatHasSubViews; 
@property (nonatomic) NSLayoutConstraint *tester; 
@end 

ContainerViewThatHasSubViews.м

@interface ContainerViewThatHasSubViews() 
@end 

@implementation ContainerViewThatHasSubViews { 
} 
    self = [super initWithFrame:frame]; 
    if (self) { 

     _subContainerOfContainerViewThatHasSubViews = [UIView new]; 
     [_subContainerOfContainerViewThatHasSubViews setTranslatesAutoresizingMaskIntoConstraints:false]; 
     [self addSubview:subContainerOfContainerViewThatHasSubViews]; 

     /// PSUEDO CODE HERE NOW 
     ALL OTHER UI ELEMENTS ARE ADDED TO THE UIVIEW "subContainerOfContainerViewThatHasSubViews" 

     like this *** [subContainerOfContainerViewThatHasSubViews addSubView:**another ui element***];*** 

     etc. etc. etc. 

     then use layout constraints like this: 

     NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:stickerController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.view.bounds.size.height]; 
     [subContainerOfContainerViewThatHasSubViews.view addConstraint:constraint]; 

     etc. etc., so the layout constraints are added to "subContainerOfContainerViewThatHasSubViews" 

     add separate constraints to this UIView for the items inside this view, and you can then animate these cosntraitns as well by declaring the constraints in your header file as propertyies like i did with the _tester constraint, you can animate these when you press a button in your UIViewController impelmentation file by addding a gesture recognizer or whatever you have to show the keyboard 

     then end with this: 

     NSDictionary* views = NSDictionaryOfVariableBindings(subContainerOfContainerViewThatHasSubViews); 
     NSDictionary* metrics = @{@"sp" : @(heightResizer(10)), @"sh" : @40}; //include sizing metrics here 

     [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_subContainerOfContainerViewThatHasSubViews]|" options:0 metrics:metrics views:views]]; 

     and this: 

     _tester =[NSLayoutConstraint constraintWithItem:_subContainerOfContainerViewThatHasSubViews attribute:NSLayoutAttributeCenterTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterTop multiplier:1.0f constant:0.0f]; 


     [self addConstraint:_tester]; 
    } 
    return self; 
} 
@end 

Gist:

https://gist.github.com/anonymous/c601481d24ad1b98b219

https://gist.github.com/anonymous/b22b68d4bf8d7fa51d66

https://gist.github.com/anonymous/a9aaf922e0f5383256b6

https://gist.github.com/anonymous/fc6655ea8200cda9c0dd

Там очень много к этому, но это только час ow программные представления работают. Я никогда не использовал раскадровку, потому что я чувствую, что у меня больше контроля, делая все программно, если вы можете справиться с тем, сколько кода вам нужно написать, чтобы это произошло, тогда вам хорошо, я знаю это, потому что я строю приложение, подобное вам, которое делает то же самое, что вы хотите, и это работает для меня, потому что я копаю глубоко в представлениях. Это полный контроль, просто убедитесь, что вы делаете другие NSLayoutContraints в качестве свойств подкласса UIView, а затем вы можете размещать методы в вашем заголовочном файле подкласса UIView, которые указывают на его файл реализации подкласса UIView, и эти методы могут быть методами анимации что вы можете звонить с вашего контроллера представления, как это:

[[self contentView] CALLYOURFUNCTION]; 

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

[[self contentView] tester]; //this is the constraint from9 the header file of tbhe custom UIView 

установить константа в вашем UIViewController делает это:

[[[self contentView] tester] setConstant:A_NUMBER]; 

Дело в том, что вы инкапсулируете все свои представления в подкласс UIView, а не получаете доступ к представлению своего контроллера представления и пытаетесь его оживить. Я никогда не видел, чтобы кто-то пытался анимировать свойство «view» самого UIViewController, я видел только анимацию UIView, которая является подвидью представления UIViewController. Точка также является то, что вы заставляете это UIView быть вид зрения UIViewControllers, а затем вы используете другой UIView внутри подклассов UIView, чтобы оживить все содержимое точки зрения, так как это:

-UIViewController's view 
    Sub Class of UIView 
     UIView <=== this is the view that contains ALL THE OTHER UIElements of the View controller 

Добавьте ограничение на UIView, которое содержит все другие элементы пользовательского интерфейса, это противоречие - это ограничение тестера, которое я добавил в заголовок пользовательского Sub class UIView.

Вы можете добавить дополнительные ограничения к подпанелям в UIView в том, что я уже упоминал, который содержит все другие элементы пользовательского интерфейса на UIViewController

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

+1

Эй, спасибо за ответ, но я думаю, мне нужно уточнить немного больше. Моя проблема связана не с анимацией в subview (она прекрасно работает), но я также пытаюсь переместить супервизор из своего пути. Так как пользовательский вид анимируется с экрана на экране, супервизор должен анимировать, чтобы освободить место для него. Извините, если я не был достаточно ясен, но я ценю это предложение. – FrostRocket

+0

Удивительно, позвольте мне подумать об этом еще, я отвечу. На самом деле, я собираюсь добавить к моему ответу, проверить этот новый материал. – Loxx

+0

. Я открою Gist, чтобы показать вам, что я имею в виду более подробно, один секунда. – Loxx

0

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

  1. Внешний вид содержимого, как обычно. Установите ведущие, трейлинг и верхние ограничения для представления содержимого и нижнее ограничение для представления контейнера (описано на шаге 2).

  2. Создайте представление контейнера и прикрепите его под содержимым. Установите равную ширину в виде содержимого, Верхнее ограничение на нижнюю часть содержимого и высоту 240 (или что угодно). Примечание: вид будет установлен в положение OFF контроллера вида. Если вы немного OCD, как я, это немного беспокоит вас, пока вы не поймете, что это k.

  3. Вот что я использовал для перемещения вида контейнера на место и просмотра содержимого с ним. Обратите внимание, что я, вероятно, буду очистить это больше, но это общая идея:

    if (_isStickersViewOpen) { 
        self.tableView.contentInset = UIEdgeInsetsZero; 
        self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero; 
    
        [UIView animateWithDuration:0.3 
             delay:0.0 
            options:UIViewAnimationOptionCurveEaseOut 
           animations:^{ 
            self.contentView.center = CGPointMake(self.scrollView.center.x, self.scrollView.center.y); 
            self.containerView.center = CGPointMake(self.scrollView.center.x, self.scrollView.bounds.size.height + self.containerView.bounds.size.height/2); 
           } 
           completion:^(BOOL finished){ 
            _isStickersViewOpen = NO; 
           }]; 
    } else { 
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.containerView.frame.size.height, 0.0, 0.0, 0.0); 
    
        self.tableView.contentInset = contentInsets; 
        self.tableView.scrollIndicatorInsets = contentInsets; 
    
        [UIView animateWithDuration:0.3 
             delay:0.0 
            options:UIViewAnimationOptionCurveEaseOut 
           animations:^{ 
            self.contentView.center = CGPointMake(self.scrollView.center.x, self.scrollView.bounds.size.height/2 - self.containerView.bounds.size.height); 
            self.containerView.center = CGPointMake(self.scrollView.center.x, self.scrollView.bounds.size.height - self.containerView.bounds.size.height/2); 
           } 
           completion:^(BOOL finished){ 
            _isStickersViewOpen = YES; 
           }]; 
    } 
    

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

+0

это отличный ответ, чистый и до нужной точки – Loxx

Смежные вопросы