Skip to content

Commit 90c75c0

Browse files
authored
Merge pull request #21 from CaliCastle/develop
Fix #19 and prevent menu offscreen
2 parents 4e81d43 + 2d7a7bd commit 90c75c0

File tree

8 files changed

+306
-115
lines changed

8 files changed

+306
-115
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1010"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "9D397AB520805CE400C58037"
18+
BuildableName = "Example.app"
19+
BlueprintName = "Example"
20+
ReferencedContainer = "container:Example.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
<BuildActionEntry
24+
buildForTesting = "NO"
25+
buildForRunning = "NO"
26+
buildForProfiling = "NO"
27+
buildForArchiving = "NO"
28+
buildForAnalyzing = "YES">
29+
<BuildableReference
30+
BuildableIdentifier = "primary"
31+
BlueprintIdentifier = "9D397A9020802C1600C58037"
32+
BuildableName = "PopMenu.framework"
33+
BlueprintName = "PopMenu"
34+
ReferencedContainer = "container:../PopMenu.xcodeproj">
35+
</BuildableReference>
36+
</BuildActionEntry>
37+
</BuildActionEntries>
38+
</BuildAction>
39+
<TestAction
40+
buildConfiguration = "Debug"
41+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43+
shouldUseLaunchSchemeArgsEnv = "YES">
44+
<Testables>
45+
</Testables>
46+
<MacroExpansion>
47+
<BuildableReference
48+
BuildableIdentifier = "primary"
49+
BlueprintIdentifier = "9D397AB520805CE400C58037"
50+
BuildableName = "Example.app"
51+
BlueprintName = "Example"
52+
ReferencedContainer = "container:Example.xcodeproj">
53+
</BuildableReference>
54+
</MacroExpansion>
55+
<AdditionalOptions>
56+
</AdditionalOptions>
57+
</TestAction>
58+
<LaunchAction
59+
buildConfiguration = "Debug"
60+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
61+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
62+
launchStyle = "0"
63+
useCustomWorkingDirectory = "NO"
64+
ignoresPersistentStateOnLaunch = "NO"
65+
debugDocumentVersioning = "YES"
66+
debugServiceExtension = "internal"
67+
allowLocationSimulation = "YES">
68+
<BuildableProductRunnable
69+
runnableDebuggingMode = "0">
70+
<BuildableReference
71+
BuildableIdentifier = "primary"
72+
BlueprintIdentifier = "9D397AB520805CE400C58037"
73+
BuildableName = "Example.app"
74+
BlueprintName = "Example"
75+
ReferencedContainer = "container:Example.xcodeproj">
76+
</BuildableReference>
77+
</BuildableProductRunnable>
78+
<AdditionalOptions>
79+
</AdditionalOptions>
80+
</LaunchAction>
81+
<ProfileAction
82+
buildConfiguration = "Release"
83+
shouldUseLaunchSchemeArgsEnv = "YES"
84+
savedToolIdentifier = ""
85+
useCustomWorkingDirectory = "NO"
86+
debugDocumentVersioning = "YES">
87+
<BuildableProductRunnable
88+
runnableDebuggingMode = "0">
89+
<BuildableReference
90+
BuildableIdentifier = "primary"
91+
BlueprintIdentifier = "9D397AB520805CE400C58037"
92+
BuildableName = "Example.app"
93+
BlueprintName = "Example"
94+
ReferencedContainer = "container:Example.xcodeproj">
95+
</BuildableReference>
96+
</BuildableProductRunnable>
97+
</ProfileAction>
98+
<AnalyzeAction
99+
buildConfiguration = "Debug">
100+
</AnalyzeAction>
101+
<ArchiveAction
102+
buildConfiguration = "Release"
103+
revealArchiveInOrganizer = "YES">
104+
</ArchiveAction>
105+
</Scheme>

Example/Example/Storyboards/Base.lproj/Main.storyboard

Lines changed: 105 additions & 99 deletions
Large diffs are not rendered by default.

Example/Example/View Controllers/Helper/PopMenuExamples.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ final class PopMenuExamples {
1919
PopMenuDefaultAction(title: "Short"),
2020
PopMenuDefaultAction(title: "A Longer Text")
2121
]
22-
22+
2323
let popMenu = PopMenuViewController(actions: actions)
2424

25+
// TODO: Not ready yet
26+
// popMenu.appearance.popMenuPresentationStyle = .near(.bottom)
27+
2528
return popMenu
2629
}
2730

Example/Example/View Controllers/RootViewController.swift

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,32 @@ class RootViewController: UITableViewController {
2222
// PopMenu examples helper instance.
2323
fileprivate let examples = PopMenuExamples()
2424

25+
// Whether or not should use manager to present menu
26+
fileprivate let shouldUseManager = true
27+
2528
// MARK: - View Life Cycle
2629

2730
override func viewDidLoad() {
2831
super.viewDidLoad()
2932

3033
}
3134

32-
/// Top right bar button tapped.
35+
/// Top left bar button tapped
36+
@IBAction func topLeftButtonDidTap(_ sender: UIBarButtonItem) {
37+
if shouldUseManager {
38+
showMenuWithManager(for: sender)
39+
} else {
40+
showMenuManually(for: sender)
41+
}
42+
}
3343

34-
@IBAction func presentMenu(_ sender: UIBarButtonItem) {
35-
showMenuManually(for: sender)
44+
/// Top right bar button tapped
45+
@IBAction func topRightButtonDidTap(_ sender: UIBarButtonItem) {
46+
if shouldUseManager {
47+
showMenuWithManager(for: sender)
48+
} else {
49+
showMenuManually(for: sender)
50+
}
3651
}
3752

3853
/// This shows how to use PopMenu the old fashion way
@@ -61,6 +76,25 @@ class RootViewController: UITableViewController {
6176
present(controller, animated: true, completion: nil)
6277
}
6378

79+
/// This shows how to use PopMenu with PopMenuManager
80+
fileprivate func showMenuWithManager(for barButtonItem: UIBarButtonItem) {
81+
// Get manager instance
82+
let manager = PopMenuManager.default
83+
// Set actions
84+
manager.actions = [
85+
PopMenuDefaultAction(title: "Click me to", image: #imageLiteral(resourceName: "Plus"), color: .yellow),
86+
PopMenuDefaultAction(title: "Pop another menu", image: #imageLiteral(resourceName: "Heart"), color: #colorLiteral(red: 0.9816910625, green: 0.5655395389, blue: 0.4352460504, alpha: 1)),
87+
PopMenuDefaultAction(title: "Try it out!", image: nil, color: .white)
88+
]
89+
// Customize appearance
90+
manager.popMenuAppearance.popMenuFont = UIFont(name: "AvenirNext-DemiBold", size: 16)!
91+
manager.popMenuAppearance.popMenuBackgroundStyle = .blurred(.dark)
92+
manager.popMenuShouldDismissOnSelection = false
93+
manager.popMenuDelegate = self
94+
// Present menu
95+
manager.present(sourceView: barButtonItem)
96+
}
97+
6498
// MARK: - Table View Row Configuration
6599

66100
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

NewPopMenu.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
Pod::Spec.new do |spec|
22
spec.name = 'NewPopMenu'
3-
spec.version = '2.1.1'
3+
spec.version = '2.1.2'
44
spec.license = { :type => 'MIT', :file => "LICENSE" }
55
spec.homepage = 'https://github.com/CaliCastle/PopMenu'
66
spec.authors = { 'Cali Castle' => 'cali@calicastle.com' }
7-
spec.summary = 'A cool and customizable popup action sheet for iOS'
8-
spec.source = { :git => 'https://github.com/CaliCastle/PopMenu.git', :tag => 'v2.1.1' }
7+
spec.summary = 'A fully customizable popup style menu'
8+
spec.source = { :git => 'https://github.com/CaliCastle/PopMenu.git', :tag => 'v2.1.2' }
99
spec.source_files = 'PopMenu/**/*.{h,swift}'
1010

1111
spec.module_name = "PopMenu"

PopMenu/Classes/PopMenuAppearance.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ final public class PopMenuAppearance: NSObject {
4747

4848
/// The status bar style of the pop menu.
4949
public var popMenuStatusBarStyle: UIStatusBarStyle?
50+
51+
/// The presentation style
52+
public var popMenuPresentationStyle: PopMenuPresentationStyle = .cover()
5053

5154
}
5255

@@ -168,3 +171,31 @@ public struct PopMenuActionSeparator: Equatable {
168171
}
169172

170173
}
174+
175+
///
176+
public struct PopMenuPresentationStyle {
177+
178+
/// The direction enum for the menu.
179+
public let direction: PopMenuDirection
180+
181+
/// Custom offset coordinates.
182+
public let offset: CGPoint?
183+
184+
/// The default presentation that covers the source view.
185+
public static func cover() -> PopMenuPresentationStyle {
186+
return PopMenuPresentationStyle(direction: .none, offset: nil)
187+
}
188+
189+
/// The custom presentation that shows near the source view in a direction and offset.
190+
public static func near(_ direction: PopMenuDirection, offset: CGPoint? = nil) -> PopMenuPresentationStyle {
191+
return PopMenuPresentationStyle(direction: direction, offset: offset)
192+
}
193+
}
194+
195+
public enum PopMenuDirection {
196+
case top
197+
case left
198+
case right
199+
case bottom
200+
case none
201+
}

PopMenu/View Controller & Views/PopMenuAction.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,11 @@ public class PopMenuDefaultAction: NSObject, PopMenuAction {
222222
UIView.animate(withDuration: 0.175, animations: {
223223
self.view.transform = CGAffineTransform.identity.scaledBy(x: 0.915, y: 0.915)
224224
self.view.backgroundColor = self.backgroundColor.withAlphaComponent(0.18)
225-
}, completion: {
226-
if $0 {
227-
UIView.animate(withDuration: 0.175, animations: {
228-
self.view.transform = .identity
229-
self.view.backgroundColor = .clear
230-
})
231-
}
225+
}, completion: { _ in
226+
UIView.animate(withDuration: 0.175, animations: {
227+
self.view.transform = .identity
228+
self.view.backgroundColor = .clear
229+
})
232230
})
233231
}
234232
}

PopMenu/View Controller & Views/PopMenuViewController.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ final public class PopMenuViewController: UIViewController {
122122

123123
// MARK: - View Life Cycle
124124

125+
/// PopMenuViewController constructor
126+
///
127+
/// - Parameters:
128+
/// - sourceView: the source view for triggering the menu
129+
/// - actions: all the menu actions
130+
/// - appearance: appearance configuration
125131
public convenience init(sourceView: AnyObject? = nil, actions: [PopMenuAction], appearance: PopMenuAppearance? = nil) {
126132
self.init(nibName: nil, bundle: nil)
127133

@@ -342,10 +348,18 @@ extension PopMenuViewController {
342348
/// - Returns: The source origin point
343349
fileprivate func calculateContentOrigin(with size: CGSize) -> CGPoint {
344350
guard let sourceFrame = absoluteSourceFrame else { return CGPoint(x: view.center.x - size.width / 2, y: view.center.y - size.height / 2) }
351+
let minContentPos: CGFloat = UIScreen.main.bounds.size.width * 0.05
352+
let maxContentPos: CGFloat = UIScreen.main.bounds.size.width * 0.95
345353

346354
// Get desired content origin point
347355
let offsetX = (size.width - sourceFrame.size.width ) / 2
348356
var desiredOrigin = CGPoint(x: sourceFrame.origin.x - offsetX, y: sourceFrame.origin.y)
357+
if (desiredOrigin.x + size.width) > maxContentPos {
358+
desiredOrigin.x = maxContentPos - size.width
359+
}
360+
if desiredOrigin.x < minContentPos {
361+
desiredOrigin.x = minContentPos
362+
}
349363

350364
// Move content in place
351365
translateOverflowX(desiredOrigin: &desiredOrigin, contentSize: size)
@@ -415,12 +429,12 @@ extension PopMenuViewController {
415429
sizingLabel.text = action.title
416430

417431
let desiredWidth = sizingLabel.sizeThatFits(view.bounds.size).width
418-
contentFitWidth += min(desiredWidth, maxContentWidth)
432+
contentFitWidth += desiredWidth
419433

420434
contentFitWidth += action.iconWidthHeight
421435
}
422436

423-
return contentFitWidth
437+
return min(contentFitWidth,maxContentWidth)
424438
}
425439

426440
/// Setup actions view.

0 commit comments

Comments
 (0)