在iOS 13中,当呈现模态视图控制器时有一个新行为。我发现内置的App Photo呈现了一个较小的模型视图控制器。
我该如何呈现一个具有这样的自定义尺寸的viewController,并且可以向上滑动到更大的高度?
系统照片应用中的图片截图。
答案 0 :(得分:3)
是的,可以在 iOS 13 中使用自定义高度显示模态。 您只需要将以下代码添加到您的演示模式
override func updateViewConstraints() {
self.view.frame.size.height = UIScreen.main.bounds.height - 150
self.view.frame.origin.y = 150
self.view.roundCorners(corners: [.topLeft, .topRight], radius: 10.0)
super.updateViewConstraints()
}
extension UIView {
func roundCorners(corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
答案 1 :(得分:0)
我不认为使用标准的UIViewController实现是可行的-即使用iOS 13的新演示样式,也只是设置演示高度。
您可能想像这样研究第三方解决方案(或从中获得启发):
答案 2 :(得分:0)
Swift答案
我一直在寻找一种方法来复制这种ViewController行为,尽管它具有基本的UI,并且找到了一个相当简单的解决方案。
基本上,您创建一个具有透明背景的ViewController(CardViewContoller
),然后向其中添加一个带有UIPanGestureReconizer
的类似于卡片的视图,这将使您可以将其拖动并通过ViewController将其关闭。
要演示,您只需调用present
,将modalPresentationStyle
设置为.overCurrentContext
,将modalTransitionStyle
设置为.coverVertical
:
let cardVC = CardViewController()
cardVC.modalPresentationStyle = .overCurrentContext
cardVC.modalTransitionStyle = .coverVertical
present(cardVC, animated: true, completion: nil)
CardViewController
中的UIPanGestureRecognizer
可以通过编程方式创建,也可以使用Interface Builder创建,将contentView
添加到名片视图(let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleDismiss(recognizer:)))
panGestureRecognizer.cancelsTouchesInView = false
contentView.addGestureRecognizer(panGestureRecognizer)
):
@objc
然后只需添加一个 @objc
func handleDismiss (recognizer: UIPanGestureRecognizer) {
switch recognizer.state {
case .changed:
viewTranslation = recognizer.translation(in: view)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
guard self.viewTranslation.y > 0 else {return}
self.view.transform = CGAffineTransform(translationX: 0, y: self.viewTranslation.y)
})
case .ended:
if viewTranslation.y < swipeThreshold {
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.view.transform = .identity
})
} else {
dismiss(animated: true, completion: nil)
}
default:
break
}
}
函数即可响应UIPanGestureRecognizer:
swipeThreshold
CGFloat
是一个UIPanGestureRecognizer
变量,具有您选择的值( 200对我而言非常有用),如果.touchUpInside
y转换超出,将触发ViewController及其所有元素的关闭。
同样,您可以添加一个简单的按钮,该按钮将在dismiss()
调用<ListView x:Name="MainMenu" Foreground="#FF5C99D6" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Focusable="False" VerticalAlignment="Top" SelectedItem="{Binding SelectedMenuItem}" ItemsSource="{Binding MenuItems}">
<ListView.ItemContainerStyle>
<Style x:Name="TestStyleName" TargetType="ListViewItem" BasedOn="{StaticResource {x:Type ListViewItem}}">
<EventSetter x:Name="TestEventName" Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDown" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="Selector.IsSelectionActive" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="Foreground" Value="Yellow" />
</MultiTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<!--REGION MAIN MENU-->
<ListViewItem x:Name="MainHome" Height="60">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Home" Height="25" Width="25" Margin="10"/>
<TextBlock Text="Home" VerticalAlignment="Center" Margin="20 10"/>
</StackPanel>
</ListViewItem>
<ListViewItem x:Name="MainSearch" Height="60">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Magnify" Height="25" Width="25" Margin="10"/>
<TextBlock Text="Search" VerticalAlignment="Center" Margin="20 10"/>
</StackPanel>
</ListViewItem>
</ListView>
如果需要,您可以看一下this repo,其中有一个展示这种行为的示例项目。这样,您可以构建自己的完全可定制的卡。