diff --git a/PanModal/Controller/PanModalPresentationController.swift b/PanModal/Controller/PanModalPresentationController.swift index 11fb2a6e..58ac9600 100644 --- a/PanModal/Controller/PanModalPresentationController.swift +++ b/PanModal/Controller/PanModalPresentationController.swift @@ -135,7 +135,13 @@ open class PanModalPresentationController: UIPresentationController { private lazy var dragIndicatorView: UIView = { let view = UIView() view.backgroundColor = presentable?.dragIndicatorBackgroundColor + var alpha: CGFloat = 1.0 + view.backgroundColor?.getRed(nil, green: nil, blue: nil, alpha: &alpha) + view.isOpaque = alpha == 1.0 view.layer.cornerRadius = Constants.dragIndicatorSize.height / 2.0 + if #available(iOS 13.0, *) { + view.layer.cornerCurve = .continuous + } return view }() @@ -188,6 +194,7 @@ open class PanModalPresentationController: UIPresentationController { coordinator.animate(alongsideTransition: { [weak self] _ in self?.backgroundView.dimState = .max + self?.dragIndicatorView.layoutIfNeeded() self?.presentedViewController.setNeedsStatusBarAppearanceUpdate() }) } @@ -347,14 +354,14 @@ private extension PanModalPresentationController { containerView.addSubview(presentedView) containerView.addGestureRecognizer(panGestureRecognizer) - if presentable.showDragIndicator { - addDragIndicatorView(to: presentedView) - } - if presentable.shouldRoundTopCorners { addRoundedCorners(to: presentedView) } + if presentable.showDragIndicator { + addDragIndicatorView(to: containerView, on: presentedView) + } + setNeedsLayoutUpdate() adjustPanContainerBackgroundColor() } @@ -376,6 +383,7 @@ private extension PanModalPresentationController { // (rotations & size changes cause positioning to be out of sync) let yPosition = panFrame.origin.y - panFrame.height + frame.height presentedView.frame.origin.y = max(yPosition, anchoredYPosition) + dragIndicatorView.frame.origin.y = presentedView.frame.origin.y - Constants.indicatorYOffset } panContainerView.frame.origin.x = frame.origin.x presentedViewController.view.frame = CGRect(origin: .zero, size: adjustedSize) @@ -396,8 +404,8 @@ private extension PanModalPresentationController { & configures its layout constraints. */ func layoutBackgroundView(in containerView: UIView) { - containerView.addSubview(backgroundView) backgroundView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(backgroundView) backgroundView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true backgroundView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true backgroundView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true @@ -408,10 +416,10 @@ private extension PanModalPresentationController { Adds the drag indicator view to the view hierarchy & configures its layout constraints. */ - func addDragIndicatorView(to view: UIView) { - view.addSubview(dragIndicatorView) + func addDragIndicatorView(to view: UIView, on pinEdgeView: UIView) { dragIndicatorView.translatesAutoresizingMaskIntoConstraints = false - dragIndicatorView.bottomAnchor.constraint(equalTo: view.topAnchor, constant: -Constants.indicatorYOffset).isActive = true + view.addSubview(dragIndicatorView) + dragIndicatorView.bottomAnchor.constraint(equalTo: pinEdgeView.topAnchor, constant: -Constants.indicatorYOffset).isActive = true dragIndicatorView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true dragIndicatorView.widthAnchor.constraint(equalToConstant: Constants.dragIndicatorSize.width).isActive = true dragIndicatorView.heightAnchor.constraint(equalToConstant: Constants.dragIndicatorSize.height).isActive = true @@ -641,7 +649,7 @@ private extension PanModalPresentationController { func snap(toYPosition yPos: CGFloat) { PanModalAnimator.animate({ [weak self] in - self?.adjust(toYPosition: yPos) + self?.adjust(toYPosition: yPos, updateDragIndicatorView: true) self?.isPresentedViewAnimating = true }, config: presentable) { [weak self] didComplete in self?.isPresentedViewAnimating = !didComplete @@ -651,8 +659,11 @@ private extension PanModalPresentationController { /** Sets the y position of the presentedView & adjusts the backgroundView. */ - func adjust(toYPosition yPos: CGFloat) { + func adjust(toYPosition yPos: CGFloat, updateDragIndicatorView: Bool = false) { presentedView.frame.origin.y = max(yPos, anchoredYPosition) + if updateDragIndicatorView { + dragIndicatorView.frame.origin.y = presentedView.frame.origin.y - Constants.indicatorYOffset + } guard presentedView.frame.origin.y > shortFormYPosition else { backgroundView.dimState = .max @@ -803,6 +814,7 @@ private extension PanModalPresentationController { as if we're transferring the scrollView drag momentum to the entire view */ presentedView.frame.origin.y = longFormYPosition - yOffset +// dragIndicatorView.frame.origin.y = presentedView.frame.origin.y - Constants.indicatorYOffset } else { scrollViewYOffset = 0 snap(toYPosition: longFormYPosition) @@ -843,39 +855,48 @@ private extension PanModalPresentationController { */ func addRoundedCorners(to view: UIView) { let radius = presentable?.cornerRadius ?? 0 - let path = UIBezierPath(roundedRect: view.bounds, - byRoundingCorners: [.topLeft, .topRight], - cornerRadii: CGSize(width: radius, height: radius)) - - // Draw around the drag indicator view, if displayed - if presentable?.showDragIndicator == true { - let indicatorLeftEdgeXPos = view.bounds.width/2.0 - Constants.dragIndicatorSize.width/2.0 - drawAroundDragIndicator(currentPath: path, indicatorLeftEdgeXPos: indicatorLeftEdgeXPos) + + if radius == 0 { + //In case removing the radius + view.layer.cornerRadius = 0 + view.layer.masksToBounds = false + return } - // Set path as a mask to display optional drag indicator view & rounded corners - let mask = CAShapeLayer() - mask.path = path.cgPath - view.layer.mask = mask + let maskedCorners: CACornerMask = CACornerMask(rawValue: createMask(corners: [.topLeft, .topRight])) + + view.layer.cornerRadius = radius + view.layer.masksToBounds = true + + if #available(iOS 11.0, *) { + view.layer.maskedCorners = maskedCorners + if #available(iOS 13.0, *) { + view.layer.cornerCurve = .continuous + } + } - // Improve performance by rasterizing the layer - view.layer.shouldRasterize = true - view.layer.rasterizationScale = UIScreen.main.scale } - /** - Draws a path around the drag indicator view - */ - func drawAroundDragIndicator(currentPath path: UIBezierPath, indicatorLeftEdgeXPos: CGFloat) { + enum Corner: Int { + case bottomRight = 0, + topRight, + bottomLeft, + topLeft + } - let totalIndicatorOffset = Constants.indicatorYOffset + Constants.dragIndicatorSize.height + private func parseCorner(corner: Corner) -> CACornerMask.Element { + let corners: [CACornerMask.Element] = [ + .layerMaxXMaxYCorner, + .layerMaxXMinYCorner, + .layerMinXMaxYCorner, + .layerMinXMinYCorner] + return corners[corner.rawValue] + } - // Draw around drag indicator starting from the left - path.addLine(to: CGPoint(x: indicatorLeftEdgeXPos, y: path.currentPoint.y)) - path.addLine(to: CGPoint(x: path.currentPoint.x, y: path.currentPoint.y - totalIndicatorOffset)) - path.addLine(to: CGPoint(x: path.currentPoint.x + Constants.dragIndicatorSize.width, y: path.currentPoint.y)) - path.addLine(to: CGPoint(x: path.currentPoint.x, y: path.currentPoint.y + totalIndicatorOffset)) + private func createMask(corners: [Corner]) -> UInt { + corners.reduce(0, { (a, b) -> UInt in a + parseCorner(corner: b).rawValue }) } + } // MARK: - Helper Extensions diff --git a/PanModal/View/PanContainerView.swift b/PanModal/View/PanContainerView.swift index f5c2892b..01c5489c 100644 --- a/PanModal/View/PanContainerView.swift +++ b/PanModal/View/PanContainerView.swift @@ -18,6 +18,9 @@ class PanContainerView: UIView { init(presentedView: UIView, frame: CGRect) { super.init(frame: frame) + var alpha: CGFloat = 1.0 + presentedView.backgroundColor?.getRed(nil, green: nil, blue: nil, alpha: &alpha) + isOpaque = alpha == 1.0 addSubview(presentedView) } diff --git a/PanModalDemo.xcodeproj/project.pbxproj b/PanModalDemo.xcodeproj/project.pbxproj index 0fe4e141..511fcdea 100644 --- a/PanModalDemo.xcodeproj/project.pbxproj +++ b/PanModalDemo.xcodeproj/project.pbxproj @@ -670,6 +670,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( @@ -690,6 +691,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Sample/View Controllers/Basic/BasicViewController.swift b/Sample/View Controllers/Basic/BasicViewController.swift index 2056651f..3e5f11af 100644 --- a/Sample/View Controllers/Basic/BasicViewController.swift +++ b/Sample/View Controllers/Basic/BasicViewController.swift @@ -12,7 +12,14 @@ class BasicViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + view.isOpaque = true view.backgroundColor = #colorLiteral(red: 0.1019607843, green: 0.1137254902, blue: 0.1294117647, alpha: 1) + let label = UILabel(frame: view.frame) + label.isOpaque = true + label.text = "Text" + label.textColor = UIColor.white + label.textAlignment = .center + view.addSubview(label) } } diff --git a/Sample/View Controllers/Full Screen/FullScreenNavController.swift b/Sample/View Controllers/Full Screen/FullScreenNavController.swift index 9dbe6215..50fee846 100644 --- a/Sample/View Controllers/Full Screen/FullScreenNavController.swift +++ b/Sample/View Controllers/Full Screen/FullScreenNavController.swift @@ -51,6 +51,7 @@ private class FullScreenViewController: UIViewController { let textLabel: UILabel = { let label = UILabel() + label.isOpaque = true label.text = "Drag downwards to dismiss" label.font = UIFont(name: "Lato-Bold", size: 17) label.translatesAutoresizingMaskIntoConstraints = false @@ -60,6 +61,7 @@ private class FullScreenViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() title = "Full Screen" + view.isOpaque = true view.backgroundColor = .white setupConstraints() } diff --git a/Sample/View Controllers/User Groups/Views/UserGroupHeaderView.swift b/Sample/View Controllers/User Groups/Views/UserGroupHeaderView.swift index 50c340f0..522e7b11 100644 --- a/Sample/View Controllers/User Groups/Views/UserGroupHeaderView.swift +++ b/Sample/View Controllers/User Groups/Views/UserGroupHeaderView.swift @@ -18,6 +18,7 @@ class UserGroupHeaderView: UIView { let titleLabel: UILabel = { let label = UILabel() + label.isOpaque = true label.font = UIFont(name: "Lato-Bold", size: 17.0) label.textColor = #colorLiteral(red: 0.8196078431, green: 0.8235294118, blue: 0.8274509804, alpha: 1) return label @@ -25,6 +26,7 @@ class UserGroupHeaderView: UIView { let subtitleLabel: UILabel = { let label = UILabel() + label.isOpaque = true label.numberOfLines = 2 label.textColor = #colorLiteral(red: 0.7019607843, green: 0.7058823529, blue: 0.7137254902, alpha: 1) label.font = UIFont(name: "Lato-Regular", size: 13.0) @@ -33,6 +35,7 @@ class UserGroupHeaderView: UIView { lazy var stackView: UIStackView = { let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) + stackView.isOpaque = true stackView.axis = .vertical stackView.alignment = .leading stackView.spacing = 4.0 @@ -42,6 +45,7 @@ class UserGroupHeaderView: UIView { let seperatorView: UIView = { let view = UIView() + view.isOpaque = true view.backgroundColor = #colorLiteral(red: 0.8196078431, green: 0.8235294118, blue: 0.8274509804, alpha: 1).withAlphaComponent(0.11) view.translatesAutoresizingMaskIntoConstraints = false return view @@ -53,6 +57,7 @@ class UserGroupHeaderView: UIView { super.init(frame: frame) backgroundColor = #colorLiteral(red: 0.1019607843, green: 0.1137254902, blue: 0.1294117647, alpha: 1) + isOpaque = true addSubview(stackView) addSubview(seperatorView) diff --git a/Sample/View Controllers/User Groups/Views/UserGroupMemberCell.swift b/Sample/View Controllers/User Groups/Views/UserGroupMemberCell.swift index 3c30a8ee..72add84d 100644 --- a/Sample/View Controllers/User Groups/Views/UserGroupMemberCell.swift +++ b/Sample/View Controllers/User Groups/Views/UserGroupMemberCell.swift @@ -23,12 +23,14 @@ class UserGroupMemberCell: UITableViewCell { let avatarView: UIView = { let view = UIView() + view.isOpaque = true view.layer.cornerRadius = 8.0 return view }() let nameLabel: UILabel = { let label = UILabel() + label.isOpaque = true label.textColor = #colorLiteral(red: 0.8196078431, green: 0.8235294118, blue: 0.8274509804, alpha: 1) label.font = UIFont(name: "Lato-Bold", size: 17.0) label.backgroundColor = .clear @@ -37,6 +39,7 @@ class UserGroupMemberCell: UITableViewCell { let roleLabel: UILabel = { let label = UILabel() + label.isOpaque = true label.textColor = #colorLiteral(red: 0.7019607843, green: 0.7058823529, blue: 0.7137254902, alpha: 1) label.backgroundColor = .clear label.font = UIFont(name: "Lato-Regular", size: 13.0) @@ -45,6 +48,7 @@ class UserGroupMemberCell: UITableViewCell { lazy var memberDetailsStackView: UIStackView = { let stackView = UIStackView(arrangedSubviews: [nameLabel, roleLabel]) + stackView.isOpaque = true stackView.axis = .vertical stackView.alignment = .leading stackView.translatesAutoresizingMaskIntoConstraints = false @@ -53,6 +57,7 @@ class UserGroupMemberCell: UITableViewCell { lazy var stackView: UIStackView = { let stackView = UIStackView(arrangedSubviews: [avatarView, memberDetailsStackView]) + stackView.isOpaque = true stackView.alignment = .center stackView.spacing = 16.0 stackView.translatesAutoresizingMaskIntoConstraints = false @@ -68,6 +73,7 @@ class UserGroupMemberCell: UITableViewCell { isAccessibilityElement = true let backgroundView = UIView() + backgroundView.isOpaque = true backgroundView.backgroundColor = #colorLiteral(red: 0.8196078431, green: 0.8235294118, blue: 0.8274509804, alpha: 1).withAlphaComponent(0.11) selectedBackgroundView = backgroundView