Как скрыть черный фон UIContextMenuInteraction/UITargetedPreview?
Я хочу добавить UIContextMenuInteraction в UIView с некоторыми прозрачными частями. Когда пользователь взаимодействует с этим представлением, iOS показывает это представление на черном фоне.
https://i.s tack.imgur.com/ZSL8D.jpg
Можно ли сделать эти части прозрачными или изменить цвет?
3 ответа
Наконец я нашел решение! Вам необходимо реализовать эту функцию, если вы хотите показать пользовательскую кривую:
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let previewTarget = UIPreviewTarget(container: self.view, center: center)
let previewParams = UIPreviewParameters()
var topLeft : CGFloat = 8
var topRight : CGFloat = 9
var bottomRight : CGFloat = 10
var bottomLeft : CGFloat = 11
let topLeftRadius = CGSize(width: topLeft, height: topLeft)
let topRightRadius = CGSize(width: topRight, height: topRight)
let bottomLeftRadius = CGSize(width: bottomLeft, height: bottomLeft)
let bottomRightRadius = CGSize(width: bottomRight, height: bottomRight)
previewParams.visiblePath = UIBezierPath(shouldRoundRect: TheExactRectYouWantToShow, topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius)
let targetView = UITargetedPreview(view: YourViewToShow, parameters: previewParams, target: previewTarget)
return targetView
}
Здесь мы рисуем UIBezierPath вокруг нашего пользовательского вида. Для этого вам может понадобиться и это расширение:
extension UIBezierPath {
convenience init(shouldRoundRect rect: CGRect, topLeftRadius: CGSize = .zero, topRightRadius: CGSize = .zero, bottomLeftRadius: CGSize = .zero, bottomRightRadius: CGSize = .zero){
self.init()
let path = CGMutablePath()
let topLeft = rect.origin
let topRight = CGPoint(x: rect.maxX, y: rect.minY)
let bottomRight = CGPoint(x: rect.maxX, y: rect.maxY)
let bottomLeft = CGPoint(x: rect.minX, y: rect.maxY)
if topLeftRadius != .zero{
path.move(to: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y))
} else {
path.move(to: CGPoint(x: topLeft.x, y: topLeft.y))
}
if topRightRadius != .zero{
path.addLine(to: CGPoint(x: topRight.x-topRightRadius.width, y: topRight.y))
path.addCurve(to: CGPoint(x: topRight.x, y: topRight.y+topRightRadius.height), control1: CGPoint(x: topRight.x, y: topRight.y), control2:CGPoint(x: topRight.x, y: topRight.y+topRightRadius.height))
} else {
path.addLine(to: CGPoint(x: topRight.x, y: topRight.y))
}
if bottomRightRadius != .zero{
path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y-bottomRightRadius.height))
path.addCurve(to: CGPoint(x: bottomRight.x-bottomRightRadius.width, y: bottomRight.y), control1: CGPoint(x: bottomRight.x, y: bottomRight.y), control2: CGPoint(x: bottomRight.x-bottomRightRadius.width, y: bottomRight.y))
} else {
path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y))
}
if bottomLeftRadius != .zero{
path.addLine(to: CGPoint(x: bottomLeft.x+bottomLeftRadius.width, y: bottomLeft.y))
path.addCurve(to: CGPoint(x: bottomLeft.x, y: bottomLeft.y-bottomLeftRadius.height), control1: CGPoint(x: bottomLeft.x, y: bottomLeft.y), control2: CGPoint(x: bottomLeft.x, y: bottomLeft.y-bottomLeftRadius.height))
} else {
path.addLine(to: CGPoint(x: bottomLeft.x, y: bottomLeft.y))
}
if topLeftRadius != .zero{
path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y+topLeftRadius.height))
path.addCurve(to: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y) , control1: CGPoint(x: topLeft.x, y: topLeft.y) , control2: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y))
} else {
path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y))
}
path.closeSubpath()
cgPath = path
}
И это:
extension UIView {
func roundCorners(topLeft: CGFloat = 0, topRight: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0) {//(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) {
let topLeftRadius = CGSize(width: topLeft, height: topLeft)
let topRightRadius = CGSize(width: topRight, height: topRight)
let bottomLeftRadius = CGSize(width: bottomLeft, height: bottomLeft)
let bottomRightRadius = CGSize(width: bottomRight, height: bottomRight)
let maskPath = UIBezierPath(shouldRoundRect: bounds, topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius)
let shape = CAShapeLayer()
shape.path = maskPath.cgPath
layer.mask = shape
}
}
Более простое решение для изменения цвета фона контекстного меню
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let previewTarget = UIPreviewTarget(container: self, center: <#your-view>.center)
let previewParams = UIPreviewParameters()
previewParams.backgroundColor = .clear
return UITargetedPreview(view: <#your-view>, parameters: previewParams, target: previewTarget)
}
Как сказал MAGiGO , вы можете использовать
previewForHighlightingContextMenuWithConfiguration
и
previewForDismissingContextMenuWithConfiguration
делегировать методы, чтобы создать свой собственный UITargetedPreview и установить его цвет фона на очистку.
func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview?
{
guard let indexPath = configuration.identifier as? IndexPath,
let cell = collectionView.cellForItem(at: indexPath)
else
{
return nil
}
let targetedPreview = UITargetedPreview(view: cell)
targetedPreview.parameters.backgroundColor = .clear
return targetedPreview
}
func collectionView(_ collectionView: UICollectionView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview?
{
guard let indexPath = configuration.identifier as? IndexPath,
let cell = collectionView.cellForItem(at: indexPath)
else
{
return nil
}
let targetedPreview = UITargetedPreview(view: cell)
targetedPreview.parameters.backgroundColor = .clear
return targetedPreview
}
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?
{
return UIContextMenuConfiguration(identifier: NSIndexPath(item: indexPath.item, section: indexPath.section), previewProvider: nil) { elements -> UIMenu? in
....
Примечание: мы проходим
NSIndexPath
в качестве идентификатора, необходимого для соответствия
NSCopying
протокол.