UIPresentationController предпочитает ContenteSize обновление анимированное
Так что у меня есть очень простой UIPresentationController, который в основном отображает contentView по центру экрана, его размер определяется контроллером представления предпочитаемым содержимым. (Это очень похоже на обычный контроллер модального представления, представленный в виде FormSheet).
То, что я пытаюсь достичь, - это возможность динамически обновлять размер представления этого контроллера представления, просто изменяя его предпочитаемый размер содержимого.
Когда я устанавливаю предпочитаемый размер содержимого, мой подкласс UIPresentationController получает информацию об этом в:
-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
Но как я могу отсюда изменить размер рамки просмотра с анимацией? Если я просто позвоню:
-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[UIView animateWithDuration:1.0 animations:^{
self.presentedView.frame = [self frameOfPresentedViewInContainerView];
} completion:nil];
}
Немедленно получает вызванный containerViewWillLayoutSubviews, и кадр изменяется без анимации.
-(void)containerViewWillLayoutSubviews
{
self.presentedView.frame = [self frameOfPresentedViewInContainerView];
}
Пожалуйста, помогите мне найти способ изменить размер анимации. Это должно быть возможно, так как он изменяет размеры с анимацией, например, когда происходит вращение.
3 ответа
Вместо установки рамки изнутри preferredContentSizeDidChangeForChildContentContainer
, тебе нужно только позвонить setNeedsLayout
а также layoutIfNeeded
в виде контейнера. Это вызываетcontainerViewWillLayoutSubviews
для вызова, который обновит кадр, используя вашу конфигурацию анимации.
Цель-C:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[UIView animateWithDuration:1.0 animations:^{
[self.containerView setNeedsLayout];
[self.containerView layoutIfNeeded];
} completion:nil];
}
Swift:
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
super.preferredContentSizeDidChange(forChildContentContainer: container)
guard let containerView = containerView else {
return
}
UIView.animate(withDuration: 1.0, animations: {
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
})
}
Альтернативный подход
В качестве альтернативы у вас не может быть анимированного блока в preferredContentSizeDidChange...
, а вместо этого поместите назначение preferredContentSize
в анимированном блоке.
Таким образом, у вас будет больше контроля над скоростью анимации отдельных переходов.
Цель-C:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[self.containerView setNeedsLayout];
[self.containerView layoutIfNeeded];
}
// In view controller:
[UIView animateWithDuration:0.25 animations:^{
self.preferredContentSize = CGSizeMake(self.view.bounds.width, 500.f);
}];
Swift:
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
super.preferredContentSizeDidChange(forChildContentContainer: container)
guard let containerView = containerView else {
return
}
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
}
// In view controller
UIView.animate(withDuration: 0.25) {
self.preferredContentSize = CGSize(width: self.view.width, height: 500)
}
Вы должны использовать автоматическую разметку. Сделайте выход из ограничения по высоте ваших контейнеров:
@property (nonatomic, strong, readwrite) IBOutlet NSLayoutConstraint *drawerViewHeightConstraint;
затем добавьте следующий код:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[super preferredContentSizeDidChangeForChildContentContainer:container];
self.drawerViewHeightConstraint.constant = container.preferredContentSize.height;
[UIView animateWithDuration:0.25
animations:^{
[self.view layoutIfNeeded];
}];
}
Это не прямой ответ на вопрос, но есть другой подход к созданию листа с изменяемым размером, чем ручное изменениеpreferredContentSize
.
В iOS 15 есть общедоступный API для представления нижнего листа с изменяемым размером (или листа по центру на iPad).
if #available(iOS 15.0, *) {
viewController.modalPresentationStyle = .pageSheet
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium(), .large()]
}
rootViewController.present(viewController, animated: true, completion: nil)
}
Теперь пользователь может сделать этоviewController
больше или меньше, просто панорамируя его.
Это работает наiPad
также.