├── PageMenuKit
├── Info.plist
├── PMKPageMenuController.swift
├── PMKPageMenuControllerDelegate.swift
├── PMKPageMenuItem.swift
├── PMKPageMenuItemEllipse.swift
├── PMKPageMenuItemHacka.swift
├── PMKPageMenuItemNHK.swift
├── PMKPageMenuItemNetLab.swift
├── PMKPageMenuItemPlain.swift
├── PMKPageMenuItemSmart.swift
├── PMKPageMenuItemSuite.swift
├── PMKPageMenuItemTab.swift
├── PMKPageMenuItemWeb.swift
└── PageMenuKit.h
├── PageMenuKitDemo
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ └── LaunchScreen.storyboard
├── BaseViewController.swift
├── DataViewController.swift
├── Info.plist
└── RootViewController.swift
├── PageMenuKitSwift.xcodeproj
└── project.pbxproj
├── README.md
└── screenshots
├── ex_Ellipse.png
├── ex_Hacka.png
├── ex_NHK.png
├── ex_NetLab.png
├── ex_Plain.png
├── ex_Smart.png
├── ex_Suite.png
├── ex_Tab.png
├── ex_Web.png
├── tab_Ellipse.png
├── tab_Hacka.png
├── tab_NHK.png
├── tab_NetLab.png
├── tab_Plain.png
├── tab_Smart.png
├── tab_Suite.png
├── tab_Tab.png
└── tab_Web.png
/PageMenuKit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | (c) 2016-2020 MagickWorX All Rights Reserved.
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuController.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuController.swift
4 | * DESCRIPTION: PageMenuKit: Paging Menu View Controller
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Sun, May 19 2019
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2019 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2019 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import Foundation
42 | import UIKit
43 |
44 | // http://stackoverflow.com/questions/1560081/how-can-i-create-a-uicolor-from-a-hex-string
45 | public extension UIColor {
46 | class func hexColor(_ hex: UInt32) -> UIColor {
47 | let r = CGFloat((hex & 0xff0000) >> 16) / 255.0
48 | let g = CGFloat((hex & 0xff00) >> 8) / 255.0
49 | let b = CGFloat((hex & 0xff)) / 255.0
50 | return UIColor(red:r, green:g, blue: b, alpha:1.0)
51 | }
52 | }
53 |
54 | let kMenuItemWidth: CGFloat = 90.0
55 | let kMenuItemHeight: CGFloat = 40.0
56 | let kMenuItemMargin: CGFloat = 10.0
57 | let kSmartTabMargin: CGFloat = 8.0
58 | let kSeparatorHeight: CGFloat = 2.0
59 | let kIndicatorHeight: CGFloat = kSeparatorHeight
60 |
61 | let kMenuItemBaseTag: Int = 170602
62 |
63 | let kHackaHexColor: UInt32 = 0x66cdaa
64 | let kJCNewsHexColor: UInt32 = 0x3fa9f5
65 | let kNetLabHexColor: UInt32 = 0x8e0c4e
66 | let kNHKNewsHexColor: UInt32 = 0x0387d2
67 |
68 | public class PMKPageMenuController: UIViewController, UIScrollViewDelegate
69 | {
70 | public weak var delegate: PMKPageMenuControllerDelegate? = nil
71 |
72 | public internal(set) var menuStyle: PMKPageMenuControllerStyle = .plain
73 | public internal(set) var titles: [String] = []
74 | public internal(set) var childControllers: [UIViewController] = []
75 | public internal(set) var menuColors: [UIColor] = []
76 |
77 | private var startIndex: Int = 0
78 |
79 | private var topBarHeight: CGFloat = 40.0
80 | private var itemMargin: CGFloat = 0.0
81 | private var separatorHeight: CGFloat = kSeparatorHeight
82 | private var indicatorHeight: CGFloat = kIndicatorHeight
83 |
84 | private var menuSeparator: CALayer = {
85 | let layer: CALayer = CALayer()
86 | layer.actions = [ "backgroundColor" : NSNull() ]
87 | return layer
88 | }()
89 | private var menuIndicator: UIView = UIView()
90 | private var menuItems: [PMKPageMenuItem] = []
91 |
92 | private lazy var pageViewController: UIPageViewController = {
93 | let style: UIPageViewController.TransitionStyle = .scroll
94 | let pageViewController = UIPageViewController(transitionStyle: style, navigationOrientation: .horizontal, options: nil)
95 | pageViewController.delegate = self
96 | pageViewController.dataSource = self
97 | return pageViewController
98 | }()
99 |
100 | private lazy var scrollView: UIScrollView = {
101 | let scrollView = UIScrollView()
102 | scrollView.backgroundColor = .clear
103 | scrollView.delegate = self
104 | scrollView.bounces = false
105 | scrollView.scrollsToTop = false
106 | scrollView.isPagingEnabled = false
107 | scrollView.showsHorizontalScrollIndicator = false
108 | return scrollView
109 | }()
110 |
111 | public static let standardColors: [UIColor] = [
112 | UIColor.hexColor(0xff7f7f),
113 | UIColor.hexColor(0xbf7fff),
114 | UIColor.hexColor(0x7f7fff),
115 | UIColor.hexColor(0x7fbfff),
116 | UIColor.hexColor(0x7fff7f),
117 | UIColor.hexColor(0xffbf7f)
118 | ]
119 |
120 | // Designated Initializer
121 | public required init(coder aDecoder: NSCoder) {
122 | fatalError("NSCoding not supported")
123 | }
124 |
125 | public init(controllers: [UIViewController],
126 | menuStyle: PMKPageMenuControllerStyle,
127 | menuColors: [UIColor] = PMKPageMenuController.standardColors,
128 | startIndex: Int = 1,
129 | topBarHeight: CGFloat) {
130 | super.init(nibName: nil, bundle: nil)
131 |
132 | self.menuStyle = menuStyle
133 | self.menuColors = menuColors
134 | self.startIndex = startIndex > 0 && startIndex < controllers.count
135 | ? startIndex - 1
136 | : 0
137 | self.topBarHeight = topBarHeight
138 | self.currentIndex = 0
139 |
140 | self.childControllers = controllers
141 |
142 | self.titles = controllers.enumerated().map {
143 | // $0.0 ... index
144 | // $0.1 ... UIViewController
145 | if let title = $0.1.value(forKey: "title") as? String, title.count > 0 {
146 | return title
147 | }
148 | else {
149 | return String(format: "Title%zd", $0.0 + 1)
150 | }
151 | }
152 |
153 | prepareForMenuStyle(menuStyle)
154 | }
155 |
156 | public override func loadView() {
157 | super.loadView()
158 |
159 | let width: CGFloat = self.view.bounds.size.width
160 |
161 | let x: CGFloat = 0.0
162 | let y: CGFloat = topBarHeight
163 | let w: CGFloat = width
164 | let h: CGFloat = kMenuItemHeight + separatorHeight
165 |
166 | scrollView.frame = CGRect(x: x, y: y, width: w, height: h)
167 | self.view.addSubview(scrollView)
168 |
169 | prepareForMenuItems()
170 | prepareForMenuSeparator()
171 | prepareForMenuIndicator()
172 | }
173 |
174 | public override func viewDidLoad() {
175 | super.viewDidLoad()
176 |
177 | changeMenuItem(at: startIndex)
178 |
179 | self.addChild(pageViewController)
180 | self.view.addSubview(pageViewController.view)
181 |
182 | let width: CGFloat = self.view.bounds.size.width
183 | let height: CGFloat = self.view.bounds.size.height
184 |
185 | let x: CGFloat = 0.0
186 | let y: CGFloat = topBarHeight + scrollView.frame.size.height
187 | let w: CGFloat = width
188 | let h: CGFloat = height - y
189 | pageViewController.view.frame = CGRect(x: x, y: y, width: w, height: h)
190 | pageViewController.didMove(toParent: self)
191 |
192 | delegate?.pageMenuController(self, didPrepare: menuItems)
193 | }
194 |
195 |
196 | // MARK: convenient method
197 | func menuColor(at index: Int) -> UIColor {
198 | let numberOfColors: Int = menuColors.count
199 | guard numberOfColors > 0 else {
200 | return PMKPageMenuController.standardColors[index % PMKPageMenuController.standardColors.count]
201 | }
202 | return menuColors[index % numberOfColors]
203 | }
204 |
205 | // MARK: - Properties
206 | var currentIndex: Int = 0 {
207 | willSet {
208 | let index = currentIndex
209 | let viewController: UIViewController = self.childControllers[index]
210 | delegate?.pageMenuController(self, didMoveTo: viewController, at: index)
211 |
212 | // タブの形状を復元
213 | let item: PMKPageMenuItem = self.menuItems[index]
214 | item.isSelected = false
215 | }
216 | didSet {
217 | self.moveIndicator(at: currentIndex)
218 | }
219 | }
220 |
221 | // MARK: - Private Methods for Indicator
222 | func moveIndicator(at index: Int) {
223 | // まずはタブを移動させる
224 | self.willMoveIndicator(at: index)
225 |
226 | // そのあとタブの装飾をする
227 | let w: CGFloat = kMenuItemWidth + itemMargin
228 | let x: CGFloat = w * CGFloat(index)
229 |
230 | let item: PMKPageMenuItem = self.menuItems[index]
231 | switch (menuStyle) {
232 | case .plain, .suite:
233 | var frame: CGRect = menuIndicator.frame
234 | frame.origin.x = x
235 | menuIndicator.frame = frame
236 | case .tab:
237 | menuSeparator.backgroundColor = item.color.cgColor
238 | menuIndicator.backgroundColor = .clear
239 | case .smart:
240 | menuIndicator.backgroundColor = item.color
241 | case .hacka:
242 | menuIndicator.backgroundColor = .clear
243 | default:
244 | break
245 | }
246 | item.isSelected = true
247 |
248 | delegate?.pageMenuController(self, didSelect: item, at: index)
249 | }
250 |
251 | func willMoveIndicator(at index: Int) {
252 | let w: CGFloat = kMenuItemWidth + itemMargin
253 | var x: CGFloat = w * CGFloat(index)
254 | let y: CGFloat = 0.0
255 |
256 | let width: CGFloat = scrollView.frame.size.width
257 | // 選択したタブを中央寄せにする計算
258 | let size: CGSize = scrollView.contentSize
259 | let leftX: CGFloat = (width - w) * 0.5 // 画面幅の半分からタブ幅の半分を引く
260 | let tabN: CGFloat = ceil(width / w) // 画面内に見えるタブの数
261 | let rightX: CGFloat = size.width - floor((tabN * 0.5 + 0.5) * w)
262 | if (x < leftX) { x = 0.0 }
263 | else if (x > rightX) { x = size.width - width }
264 | else { x -= leftX }
265 | scrollView.setContentOffset(CGPoint(x: x, y: y), animated: true)
266 | }
267 | }
268 |
269 | // MARK: - Prepartions
270 | extension PMKPageMenuController
271 | {
272 | // CUSTOM: Add the settings for your custom menu style here.
273 | func prepareForMenuStyle(_ menuStyle: PMKPageMenuControllerStyle) {
274 | switch (menuStyle) {
275 | case .plain:
276 | itemMargin = kMenuItemMargin
277 | separatorHeight = 1.0
278 | indicatorHeight = 3.0
279 | case .tab:
280 | itemMargin = 0.0
281 | separatorHeight = 4.0
282 | indicatorHeight = 4.0
283 | case .smart:
284 | itemMargin = 0.0
285 | separatorHeight = 0.0
286 | case .hacka:
287 | itemMargin = kMenuItemMargin * 0.4
288 | case .web:
289 | itemMargin = 0.0
290 | separatorHeight = 4.0
291 | indicatorHeight = 0.0
292 | case .ellipse, .netlab:
293 | itemMargin = 0.0
294 | separatorHeight = 0.0
295 | indicatorHeight = 0.0
296 | case .suite:
297 | itemMargin = 0.0
298 | separatorHeight = 0.0
299 | indicatorHeight = 4.0
300 | case .nhk:
301 | itemMargin = 0.0
302 | separatorHeight = 2.0
303 | indicatorHeight = 0.0
304 | }
305 | }
306 |
307 | // CUSTOM: Add the separator color for your custom menu style if needed.
308 | func prepareForMenuSeparator() {
309 | let color: UIColor = {
310 | if let firstColor: UIColor = menuColors.first { return firstColor }
311 | switch (menuStyle) {
312 | case .plain, .web: return .orange
313 | case .hacka: return UIColor.hexColor(kHackaHexColor)
314 | case .nhk: return UIColor.hexColor(kNHKNewsHexColor)
315 | default: return PMKPageMenuController.standardColors.first!
316 | }
317 | }()
318 | let width: CGFloat = scrollView.contentSize.width
319 | let height: CGFloat = scrollView.frame.size.height
320 |
321 | let w: CGFloat = width
322 | let h: CGFloat = separatorHeight
323 | let x: CGFloat = 0.0
324 | let y: CGFloat = height - h
325 |
326 | menuSeparator.frame = CGRect(x: x, y: y, width: w, height: h)
327 | menuSeparator.backgroundColor = color.cgColor
328 | scrollView.layer.addSublayer(menuSeparator)
329 | }
330 |
331 | // CUSTOM: Add the indicator color for your custom menu style if needed.
332 | func prepareForMenuIndicator() {
333 | let x: CGFloat = 0.0
334 | let y: CGFloat = scrollView.frame.size.height - indicatorHeight
335 | let w: CGFloat = menuStyle == .tab || menuStyle == .smart
336 | ? scrollView.contentSize.width
337 | : kMenuItemWidth
338 | let h: CGFloat = indicatorHeight
339 |
340 | let color: UIColor = {
341 | if let firstColor: UIColor = menuColors.first { return firstColor }
342 | switch (menuStyle) {
343 | case .plain: return .orange
344 | case .hacka: return UIColor.hexColor(kHackaHexColor)
345 | case .suite: return UIColor.hexColor(0x7ab7cc)
346 | default: return PMKPageMenuController.standardColors.first!
347 | }
348 | }()
349 |
350 | menuIndicator.frame = CGRect(x: x, y: y, width: w, height: h)
351 | menuIndicator.backgroundColor = color
352 | scrollView.addSubview(menuIndicator)
353 | }
354 |
355 | fileprivate func changeMenuItem(at index: Int) {
356 | let viewController: UIViewController = self.childControllers[index]
357 | let viewControllers: [UIViewController] = [viewController]
358 | let direction: UIPageViewController.NavigationDirection = (index > currentIndex) ? .forward : .reverse
359 | self.currentIndex = index
360 | pageViewController.setViewControllers(viewControllers, direction: direction, animated: true, completion: nil)
361 | }
362 |
363 | @objc func handleSingleTap(_ gesture: UITapGestureRecognizer) {
364 | if var index: Int = gesture.view?.tag {
365 | index -= kMenuItemBaseTag
366 | changeMenuItem(at: index)
367 | }
368 | }
369 |
370 | /*
371 | * swift3 - how to create instance of a class from a string in swift 3
372 | * https://stackoverflow.com/questions/40373030/how-to-create-instance-of-a-class-from-a-string-in-swift-3
373 | */
374 | func stringClassFromString(_ className: String) -> AnyClass! {
375 | // get namespace
376 | let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
377 | // XXX: 順に "namespace" を変更して探索を試みる
378 | if let cls: AnyClass = NSClassFromString("PageMenuKitSwift.\(className)") {
379 | return cls
380 | }
381 | if let cls: AnyClass = NSClassFromString("PageMenuKit.\(className)") {
382 | return cls
383 | }
384 | // get 'anyClass' with classname and namespace
385 | let cls: AnyClass = NSClassFromString("\(namespace).\(className)")!
386 | // return AnyClass
387 | return cls
388 | }
389 |
390 | // CUSTOM: Add the code to create instance of your custom menu style.
391 | func prepareForMenuItems() {
392 | self.menuItems = []
393 |
394 | var x: CGFloat = 0.0
395 | let y: CGFloat = menuStyle == .smart || menuStyle == .hacka
396 | ? kSmartTabMargin
397 | : 0.0
398 | let w: CGFloat = kMenuItemWidth
399 | let h: CGFloat = kMenuItemHeight - y
400 |
401 | let count: Int = self.titles.count
402 | for i in 0 ..< count {
403 | let frame: CGRect = CGRect(x: x, y: y, width: w, height: h)
404 | let title: String = self.titles[i]
405 | let color: UIColor = {
406 | if menuColors.count == 0 { // 色指定がない場合はデフォルト色を使用
407 | switch (menuStyle) {
408 | case .plain: return .orange
409 | case .hacka: return UIColor.hexColor(kHackaHexColor)
410 | case .ellipse: return UIColor.hexColor(kJCNewsHexColor)
411 | case .netlab: return UIColor.hexColor(kNetLabHexColor)
412 | case .nhk: return UIColor.hexColor(kNHKNewsHexColor)
413 | default: return self.menuColor(at: i)
414 | }
415 | }
416 | switch (menuStyle) {
417 | case .plain, .hacka, .ellipse, .netlab, .nhk:
418 | return self.menuColor(at: 0)
419 | default:
420 | return self.menuColor(at: i)
421 | }
422 | }()
423 |
424 | let design = PMKPageMenuItemDesign(themeColor: color)
425 | switch (menuStyle) { // set default design
426 | case .web:
427 | design.inactive.isEnabled = true
428 | design.inactive.backgroundColor = UIColor.hexColor(0x332f2e)
429 | case .suite:
430 | design.titleColor = .white
431 | design.gradientColors = [
432 | UIColor.hexColor(0x445a66).cgColor,
433 | UIColor.hexColor(0x677983).cgColor
434 | ]
435 | design.inactive.isEnabled = true
436 | design.inactive.titleColor = .lightGray
437 | case .netlab:
438 | design.backgroundColor = UIColor.hexColor(0xcb8fad)
439 | default:
440 | break
441 | }
442 |
443 | let className = menuStyle.className()
444 | let classType = stringClassFromString(className) as! PMKPageMenuItem.Type
445 | let item: PMKPageMenuItem = classType.init(frame: frame, title: title, design: design)
446 | item.tag = kMenuItemBaseTag + i
447 | scrollView.addSubview(item)
448 | x += (w + itemMargin)
449 |
450 | item.isSelected = (i == 0)
451 | self.menuItems.append(item)
452 |
453 | let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap(_:)))
454 | item.addGestureRecognizer(tapGesture)
455 | }
456 |
457 | let width: CGFloat = scrollView.bounds.size.width
458 | let height: CGFloat = scrollView.bounds.size.height
459 | scrollView.contentSize = CGSize(width: x, height: height)
460 |
461 | var frame: CGRect = scrollView.frame
462 | if (width > x) { // 項目が少ないのね
463 | frame.origin.x = floor((width - x) * 0.5)
464 | frame.size.width = x
465 | }
466 | else {
467 | frame.origin.x = 0.0
468 | frame.size.width = width
469 | }
470 | scrollView.frame = frame
471 | }
472 |
473 | }
474 |
475 | // MARK: - Public Methods
476 | extension PMKPageMenuController
477 | {
478 | public func setMenuSeparatorColor(_ color: UIColor) {
479 | menuSeparator.backgroundColor = color.cgColor
480 | }
481 |
482 | public func setMenuIndicatorColor(_ color: UIColor) {
483 | menuIndicator.backgroundColor = color
484 | }
485 |
486 | }
487 |
488 | /*
489 | * MARK: - UIPageViewControllerDelegate
490 | */
491 | extension PMKPageMenuController: UIPageViewControllerDelegate
492 | {
493 | // MARK - UIPageViewControllerDelegate (optional)
494 | public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
495 | if let viewController: UIViewController = pendingViewControllers.last {
496 | if let index = self.childControllers.firstIndex(of: viewController) {
497 | if index != currentIndex {
498 | self.willMoveIndicator(at: index)
499 | }
500 | delegate?.pageMenuController(self, willMoveTo: viewController, at: index)
501 | }
502 | }
503 | }
504 |
505 | // MARK - UIPageViewControllerDelegate (optional)
506 | public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
507 | if let viewController: UIViewController = pageViewController.viewControllers?.last {
508 | guard let index = self.childControllers.firstIndex(of: viewController) else { return }
509 | if completed {
510 | self.currentIndex = index
511 | }
512 | else {
513 | self.willMoveIndicator(at: index)
514 | }
515 | }
516 | }
517 |
518 | // MARK - UIPageViewControllerDelegate (optional)
519 | public func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
520 | if orientation.isPortrait || UIDevice.current.userInterfaceIdiom == .phone {
521 | if let currentViewController: UIViewController = pageViewController.viewControllers?.first {
522 | let viewControllers: [UIViewController] = [currentViewController]
523 | pageViewController.setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
524 | }
525 | pageViewController.isDoubleSided = false
526 | return .min
527 | }
528 | return .none
529 | }
530 |
531 | }
532 |
533 | /*
534 | * MARK: - UIPageViewControllerDataSource
535 | */
536 | extension PMKPageMenuController: UIPageViewControllerDataSource
537 | {
538 | // MARK - UIPageViewControllerDataSource (required)
539 | public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
540 | if let index = self.childControllers.firstIndex(of: viewController) {
541 | if index != 0 && index != NSNotFound {
542 | return self.childControllers[index - 1]
543 | }
544 | }
545 | return nil
546 | }
547 |
548 | // MARK - UIPageViewControllerDataSource (required)
549 | public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
550 | if let index = self.childControllers.firstIndex(of: viewController) {
551 | let count: Int = self.childControllers.count
552 | if index != NSNotFound && index + 1 < count {
553 | return self.childControllers[index + 1]
554 | }
555 | }
556 | return nil
557 | }
558 |
559 | }
560 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuControllerDelegate.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuControllerDelegate.swift
4 | * DESCRIPTION: PageMenuKit: Delegate for PageMenuController
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Jun 8 2017
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 |
43 | public protocol PMKPageMenuControllerDelegate: class
44 | {
45 | // ページ画面上でスワイプ操作による切り替えが行われる前に呼び出される
46 | func pageMenuController(_ pageMenuController: PMKPageMenuController, willMoveTo viewController: UIViewController, at menuIndex: Int)
47 | // ページの切り替えが完了した際に呼び出される
48 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didMoveTo viewController: UIViewController, at menuIndex: Int)
49 |
50 | // メニュー項目の作成などが完了した際に呼び出される
51 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didPrepare menuItems: [PMKPageMenuItem])
52 | // メニューがタップされた際に呼び出される
53 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didSelect menuItem: PMKPageMenuItem, at menuIndex: Int)
54 | }
55 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItem.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItem.swift
4 | * DESCRIPTION: PageMenuKit: Base MenuItem Class for PageMenuController
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | // CUSTOM: Add your custom menu style here.
45 | public enum PMKPageMenuControllerStyle: Int {
46 | case plain = 1 // NewsPass [https://itunes.apple.com/jp/app/id1106788059]
47 | case tab = 2 // Gunosy [https://itunes.apple.com/jp/app/id590384791]
48 | case smart = 3 // SmartNews [https://itunes.apple.com/jp/app/id579581125]
49 | case hacka = 4 // Hackadoll [https://itunes.apple.com/jp/app/id888231424]
50 | case web = 5 // JCNews [https://jcnews.tokyo/)
51 | case ellipse = 6 // JCNews [https://itunes.apple.com/jp/app/id1024341813]
52 | case suite = 7 // NewsSuite [https://itunes.apple.com/jp/app/id1176431318]
53 | case netlab = 8 // NLab [https://itunes.apple.com/jp/app/id949325541]
54 | case nhk = 9 // NHK NEWS [https://itunes.apple.com/jp/app/id1121104608]
55 |
56 | /// メニュー画面のスタイル毎のクラス名を返す
57 | ///
58 | /// - Returns: クラス名
59 | func className() -> String {
60 | switch self {
61 | case .plain: return "PMKPageMenuItemPlain"
62 | case .tab: return "PMKPageMenuItemTab"
63 | case .smart: return "PMKPageMenuItemSmart"
64 | case .hacka: return "PMKPageMenuItemHacka"
65 | case .web: return "PMKPageMenuItemWeb"
66 | case .ellipse: return "PMKPageMenuItemEllipse"
67 | case .suite: return "PMKPageMenuItemSuite"
68 | case .netlab: return "PMKPageMenuItemNetLab"
69 | case .nhk: return "PMKPageMenuItemNHK"
70 | }
71 | }
72 | }
73 |
74 |
75 | protocol Design {
76 | var themeColor: UIColor { get set }
77 | var titleColor: UIColor { get set }
78 | var backgroundColor: UIColor { get set }
79 | }
80 |
81 | public class PMKPageMenuItemDesign: Design {
82 | var themeColor: UIColor = .clear // 通常は titleColor と同じはず
83 | var titleColor: UIColor = .black
84 | var backgroundColor: UIColor = .clear
85 | var gradientColors: [CGColor] = []
86 |
87 | struct InactiveDesign { // inactive を有効にする場合は isEnabled = true にする
88 | var isEnabled: Bool = false
89 | var titleColor: UIColor = .lightGray
90 | var backgroundColor: UIColor = .clear
91 | }
92 | var inactive: InactiveDesign = PMKPageMenuItemDesign.InactiveDesign()
93 |
94 | public init(themeColor: UIColor) {
95 | self.themeColor = themeColor
96 | self.titleColor = themeColor
97 | }
98 |
99 | public init() {
100 | }
101 | }
102 |
103 |
104 | protocol Item {
105 | var title: String { get set }
106 | var isEnabled: Bool { get set }
107 | }
108 |
109 | protocol MenuItem: Item {
110 | var color: UIColor { get set } // メニューの基本色
111 | var titleColor: UIColor { get set }
112 | var borderColor: UIColor { get set } // メニュー枠の色
113 | var isSelected: Bool { get set }
114 |
115 | /// メニュー画面を装飾
116 | ///
117 | /// - Rarameters:
118 | /// - active: メニュー選択時 = true, 非選択時 = false
119 | /// - Returns: なし
120 | func render(active: Bool)
121 | }
122 |
123 | public class PMKPageMenuItem: UIView, MenuItem {
124 | let kBorderLayerKey: String = "kBorderLayerKey"
125 |
126 | public internal(set) var color: UIColor = .clear
127 | public internal(set) var design: PMKPageMenuItemDesign = PMKPageMenuItemDesign()
128 | public internal(set) var style: PMKPageMenuControllerStyle = .plain
129 |
130 | lazy var label: UILabel = {
131 | let label = UILabel()
132 | label.text = self.title
133 | label.textAlignment = .center
134 | label.backgroundColor = .clear
135 | label.autoresizingMask = [ .flexibleWidth, .flexibleHeight ]
136 | return label
137 | }()
138 |
139 | public required init(coder aDecoder: NSCoder) {
140 | fatalError("init(coder:) has not been implemented")
141 | }
142 |
143 | override init(frame: CGRect) {
144 | super.init(frame: frame)
145 | }
146 |
147 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
148 | super.init(frame: frame)
149 |
150 | self.backgroundColor = .clear
151 | self.isUserInteractionEnabled = true
152 | self.autoresizesSubviews = true
153 |
154 | self.title = title
155 | self.color = design.themeColor
156 | self.design = design
157 |
158 | label.frame = self.bounds
159 | self.addSubview(label)
160 | }
161 |
162 |
163 | /*
164 | * Properties
165 | */
166 | public var title: String = "" {
167 | willSet {
168 | if title != newValue {
169 | label.text = newValue
170 | }
171 | }
172 | }
173 |
174 | public var isEnabled: Bool = true {
175 | willSet {
176 | label.isUserInteractionEnabled = newValue
177 | label.alpha = newValue ? 1.0 : 0.5
178 | }
179 | }
180 |
181 | var titleColor: UIColor = .black {
182 | willSet {
183 | label.textColor = newValue
184 | }
185 | }
186 |
187 | var borderColor: UIColor = .clear
188 |
189 | public var isSelected: Bool = false {
190 | willSet {
191 | self.render(active: newValue)
192 | }
193 | }
194 |
195 | public var badgeValue: String? = nil // XXX: Override Point
196 |
197 | // MARK: - Overriden Functions
198 | func render(active: Bool) {
199 | }
200 |
201 | // 左上と右上の角を丸める
202 | func roundCorners(of label: UILabel) {
203 | autoreleasepool {
204 | let maskPath: UIBezierPath = UIBezierPath(roundedRect: label.bounds, byRoundingCorners: [ .topLeft, .topRight ], cornerRadii: CGSize(width: 5.0, height: 5.0))
205 | let maskLayer: CAShapeLayer = CAShapeLayer()
206 | maskLayer.frame = label.bounds
207 | maskLayer.path = maskPath.cgPath
208 | label.layer.mask = maskLayer
209 | }
210 | }
211 | }
212 |
213 | // MARK: - Private Methods
214 | extension PMKPageMenuItem {
215 | public var borderLayer: CAShapeLayer? {
216 | return label.layer.value(forKey: kBorderLayerKey) as? CAShapeLayer
217 | }
218 |
219 | // 左端と上と右端のみ枠線を付ける
220 | func addBorders(to label: UILabel) {
221 | autoreleasepool {
222 | let w: CGFloat = label.frame.size.width
223 | let h: CGFloat = label.frame.size.height
224 | var x: CGFloat = 0.0
225 | var y: CGFloat = h
226 | let bezierPath: UIBezierPath = UIBezierPath()
227 | bezierPath.move(to: CGPoint(x: x, y: y)); y = 0.0
228 | bezierPath.addLine(to: CGPoint(x: x, y: y)); x = w
229 | bezierPath.addLine(to: CGPoint(x: x, y: y)); y = h
230 | bezierPath.addLine(to: CGPoint(x: x, y: y))
231 | let shapeLayer: CAShapeLayer = CAShapeLayer()
232 | shapeLayer.frame = label.bounds
233 | shapeLayer.path = bezierPath.cgPath
234 | shapeLayer.fillColor = UIColor.clear.cgColor
235 | shapeLayer.strokeColor = self.borderColor.cgColor
236 | shapeLayer.lineWidth = 1.0
237 | /*
238 | * XXX: Disable implicit animation for hidden of CAShapeLayer.
239 | * http://stackoverflow.com/questions/5833488/how-to-disable-calayer-implicit-animations
240 | */
241 | shapeLayer.actions = [ "hidden" : NSNull() ]
242 | label.layer.addSublayer(shapeLayer)
243 | label.layer.setValue(shapeLayer, forKey:kBorderLayerKey)
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemEllipse.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemEllipse.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "JCNews" iOS App
5 | * DATE: Wed, Jun 7 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemEllipse: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .ellipse
53 |
54 | self.backgroundColor = design.themeColor // ベースの背景色は固定
55 | }
56 |
57 | override func render(active: Bool) {
58 | if active {
59 | self.label.textColor = self.design.themeColor
60 | self.label.backgroundColor = .white
61 | self.roundCorners(of: self.label)
62 | }
63 | else {
64 | self.label.textColor = .white
65 | self.label.backgroundColor = self.design.themeColor
66 | self.label.layer.mask = nil
67 | }
68 | }
69 |
70 | override func roundCorners(of label: UILabel) {
71 | autoreleasepool {
72 | let radius: CGFloat = 10.0
73 | let bounds: CGRect = label.bounds.insetBy(dx: 4.0, dy: 6.0)
74 | let maskPath: UIBezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [ .allCorners ], cornerRadii: CGSize(width: radius, height: radius))
75 | let maskLayer: CAShapeLayer = CAShapeLayer()
76 | maskLayer.frame = label.bounds
77 | maskLayer.path = maskPath.cgPath
78 | label.layer.mask = maskLayer
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemHacka.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemHacka.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "ハッカドール" iOS App
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemHacka: PMKPageMenuItem {
45 | let kBadgeLayerKey: String = "kBadgeLayerKey"
46 |
47 | public required init(coder aDecoder: NSCoder) {
48 | fatalError("init(coder:) has not been implemented")
49 | }
50 |
51 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
52 | super.init(frame: frame, title: title, design: design)
53 |
54 | self.style = .hacka
55 | self.titleColor = design.themeColor
56 | self.borderColor = design.themeColor
57 |
58 | self.addBorders(to: self.label)
59 | }
60 |
61 | override func render(active: Bool) {
62 | var frame: CGRect = self.frame
63 | if active {
64 | self.label.textColor = .white
65 | self.label.backgroundColor = self.design.themeColor
66 | self.borderLayer?.isHidden = true
67 | frame.origin.y = 0.0
68 | frame.size.height = kMenuItemHeight
69 | }
70 | else {
71 | self.label.textColor = self.design.themeColor
72 | self.label.backgroundColor = .clear
73 | self.borderLayer?.isHidden = false
74 | frame.origin.y = kSmartTabMargin
75 | frame.size.height = kMenuItemHeight - kSmartTabMargin
76 | }
77 | self.frame = frame
78 |
79 | if let textLayer = self.label.layer.value(forKey: kBadgeLayerKey) as? CATextLayer {
80 | textLayer.isHidden = (self.badgeValue == nil || active)
81 | }
82 | }
83 |
84 | override var borderColor: UIColor {
85 | willSet {
86 | self.borderLayer?.strokeColor = newValue.cgColor
87 | }
88 | }
89 |
90 | override public var badgeValue: String? {
91 | willSet {
92 | let textLayer: CATextLayer = {
93 | if let textLayer = self.label.layer.value(forKey: kBadgeLayerKey) as? CATextLayer {
94 | return textLayer
95 | }
96 | let w: CGFloat = 16.0
97 | let h: CGFloat = w
98 | let x: CGFloat = self.label.frame.size.width - w - 4.0
99 | let y: CGFloat = -kSmartTabMargin
100 | let textLayer = CATextLayer()
101 | textLayer.frame = CGRect(x: x, y: y, width: w, height: h)
102 | textLayer.fontSize = 12.0
103 | textLayer.foregroundColor = UIColor.white.cgColor
104 | textLayer.backgroundColor = UIColor.red.cgColor
105 | textLayer.cornerRadius = w * 0.5
106 | textLayer.masksToBounds = true
107 | textLayer.alignmentMode = .center
108 | textLayer.contentsScale = UIScreen.main.scale
109 | textLayer.actions = [ "hidden" : NSNull() ]
110 | self.label.layer.addSublayer(textLayer)
111 | self.label.layer.setValue(textLayer, forKey: kBadgeLayerKey)
112 | return textLayer
113 | }()
114 | textLayer.string = newValue
115 | textLayer.isHidden = (newValue == nil || isSelected)
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemNHK.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemNHK.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "NHK ニュース防災"
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemNHK: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .nhk
53 | }
54 |
55 | override func render(active: Bool) {
56 | if active {
57 | self.label.textColor = .white
58 | self.label.backgroundColor = self.design.themeColor
59 | }
60 | else {
61 | self.label.textColor = self.design.themeColor
62 | self.label.backgroundColor = .clear
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemNetLab.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemNetLab.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "ねとらぼ" iOS App
5 | * DATE: Thu, Jun 8 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemNetLab: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .netlab
53 | }
54 |
55 | override func render(active: Bool) {
56 | if active {
57 | self.label.textColor = .white
58 | self.label.backgroundColor = self.design.backgroundColor
59 | self.roundCorners(of: self.label)
60 | }
61 | else {
62 | self.label.textColor = self.design.titleColor
63 | self.label.backgroundColor = .clear
64 | self.label.layer.mask = nil
65 | }
66 | }
67 |
68 | override func roundCorners(of label: UILabel) {
69 | autoreleasepool {
70 | let radius: CGFloat = 5.0
71 | let bounds: CGRect = label.bounds.insetBy(dx: 4.0, dy: 6.0)
72 | let maskPath: UIBezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [ .allCorners ], cornerRadii: CGSize(width: radius, height: radius))
73 | let maskLayer: CAShapeLayer = CAShapeLayer()
74 | maskLayer.frame = label.bounds
75 | maskLayer.path = maskPath.cgPath
76 | label.layer.mask = maskLayer
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemPlain.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemPlain.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "ニュースパス"
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemPlain: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .plain
53 |
54 | self.titleColor = design.titleColor
55 | }
56 |
57 | override func render(active: Bool) {
58 | self.label.textColor = active ? self.design.titleColor : .darkGray
59 | self.label.backgroundColor = .clear
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemSmart.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemSmart.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "SmartNews"
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemSmart: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .smart
53 |
54 | self.titleColor = .white
55 | self.label.backgroundColor = design.themeColor
56 | }
57 |
58 | override func render(active: Bool) {
59 | var frame: CGRect = self.frame
60 | if active {
61 | frame.origin.y = 0.0
62 | frame.size.height = kMenuItemHeight
63 | }
64 | else {
65 | frame.origin.y = kSmartTabMargin
66 | frame.size.height = kMenuItemHeight - kSmartTabMargin
67 | }
68 | self.frame = frame
69 | self.roundCorners(of: self.label)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemSuite.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemSuite.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "ニュース(News Suite)"
5 | * DATE: Wed, Jun 7 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemSuite: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .suite
53 |
54 | self.gradientBackground(of: self)
55 | }
56 |
57 | override func render(active: Bool) {
58 | self.label.textColor = {
59 | if active {
60 | return self.design.titleColor
61 | }
62 | else if self.design.inactive.isEnabled {
63 | return self.design.inactive.titleColor
64 | }
65 | else {
66 | return .lightGray
67 | }
68 | }()
69 | }
70 |
71 | func gradientBackground(of view: UIView) {
72 | let gradientColors: [CGColor] = {
73 | if self.design.gradientColors.count > 0 {
74 | return self.design.gradientColors
75 | }
76 | let topColor: UIColor = UIColor.hexColor(0x445a66)
77 | let bottomColor: UIColor = UIColor.hexColor(0x677983)
78 | return [ topColor.cgColor, bottomColor.cgColor ]
79 | }()
80 | let gradientLayer: CAGradientLayer = CAGradientLayer()
81 | gradientLayer.colors = gradientColors
82 | gradientLayer.frame = view.bounds
83 | view.layer.insertSublayer(gradientLayer, at: 0)
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemTab.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemTab.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "グノシー"
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 | import QuartzCore
43 |
44 | public class PMKPageMenuItemTab: PMKPageMenuItem {
45 | public required init(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
50 | super.init(frame: frame, title: title, design: design)
51 |
52 | self.style = .tab
53 |
54 | self.roundCorners(of: self.label)
55 | }
56 |
57 | override func render(active: Bool) {
58 | if active {
59 | self.label.textColor = .white
60 | self.label.backgroundColor = self.design.themeColor
61 | }
62 | else {
63 | self.label.textColor = self.design.themeColor
64 | self.label.backgroundColor = .clear
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/PageMenuKit/PMKPageMenuItemWeb.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: PMKPageMenuItemWeb.swift
4 | * DESCRIPTION: PageMenuKit: PageMenuItem Class like "JCNews.tokyo" Web Site
5 | * DATE: Wed, Jun 7 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | *****************************************************************************/
40 |
41 | import UIKit
42 |
43 | public class PMKPageMenuItemWeb: PMKPageMenuItem {
44 | public required init(coder aDecoder: NSCoder) {
45 | fatalError("init(coder:) has not been implemented")
46 | }
47 |
48 | public required init(frame: CGRect, title: String, design: PMKPageMenuItemDesign) {
49 | super.init(frame: frame, title: title, design: design)
50 |
51 | self.style = .web
52 | }
53 |
54 | override func render(active: Bool) {
55 | self.label.textColor = .white
56 | self.label.backgroundColor = {
57 | if active {
58 | return self.design.themeColor
59 | }
60 | else if self.design.inactive.isEnabled {
61 | return self.design.inactive.backgroundColor
62 | }
63 | else {
64 | return UIColor.hexColor(0x332f2e)
65 | }
66 | }()
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/PageMenuKit/PageMenuKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // PageMenuKit.h
3 | // PageMenuKit
4 | //
5 | // Created by Kouichi ABE (WALL) on 2017/06/08.
6 | // Copyright © 2017年 Kouichi ABE (WALL). All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for PageMenuKit.
12 | FOUNDATION_EXPORT double PageMenuKitVersionNumber;
13 |
14 | //! Project version string for PageMenuKit.
15 | FOUNDATION_EXPORT const unsigned char PageMenuKitVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: AppDelegate.swift
4 | * DESCRIPTION: PageMenuKitDemo: Application Main Controller
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Thu, Nov 15 2018
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2018 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2018 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | * $Id: AppDelegate.m,v 1.6 2017/04/12 09:59:00 kouichi Exp $
40 | *
41 | *****************************************************************************/
42 |
43 | import UIKit
44 |
45 | @UIApplicationMain
46 | class AppDelegate: UIResponder, UIApplicationDelegate
47 | {
48 | open private(set) var themeColor: UIColor? = nil
49 |
50 | var window: UIWindow?
51 |
52 | override init() {
53 | super.init()
54 | }
55 |
56 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
57 | // Override point for customization after application launch.
58 |
59 | // Create full-screen window
60 | self.window = UIWindow(frame: UIScreen.main.bounds)
61 | self.window!.backgroundColor = .white
62 |
63 | // Make root view controller
64 | self.window!.rootViewController = RootViewController()
65 |
66 | // Show window
67 | self.window!.makeKeyAndVisible()
68 |
69 | return true
70 | }
71 |
72 | func applicationWillResignActive(_ application: UIApplication) {
73 | /*
74 | * Sent when the application is about to move from active to inactive state.
75 | * This can occur for certain types of temporary interruptions (such as an
76 | * incoming phone call or SMS message) or when the user quits
77 | * the application and it begins the transition to the background state.
78 | * Use this method to pause ongoing tasks, disable timers, and invalidate
79 | * graphics rendering callbacks. Games should use this method to pause
80 | * the game.
81 | */
82 | }
83 |
84 | func applicationDidEnterBackground(_ application: UIApplication) {
85 | /*
86 | * Use this method to release shared resources, save user data,
87 | * invalidate timers, and store enough application state information
88 | * to restore your application to its current state in case it is
89 | * terminated later.
90 | * If your application supports background execution, this method is called
91 | * instead of applicationWillTerminate: when the user quits.
92 | */
93 | }
94 |
95 | func applicationWillEnterForeground(_ application: UIApplication) {
96 | /*
97 | * Called as part of the transition from the background to the active state;
98 | * here you can undo many of the changes made on entering the background.
99 | */
100 | }
101 |
102 | func applicationDidBecomeActive(_ application: UIApplication) {
103 | /*
104 | * Restart any tasks that were paused (or not yet started)
105 | * while the application was inactive. If the application was previously
106 | * in the background, optionally refresh the user interface.
107 | */
108 | }
109 |
110 | func applicationWillTerminate(_ application: UIApplication) {
111 | /*
112 | * Called when the application is about to terminate.
113 | * Save data if appropriate. See also applicationDidEnterBackground:.
114 | */
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/PageMenuKitDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/BaseViewController.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: BaseViewController.swift
4 | * DESCRIPTION: PageMenuKitDemo: Application Base View Controller
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Wed, Nov 29 2017
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | * $Id: AppDelegate.m,v 1.6 2017/04/12 09:59:00 kouichi Exp $
40 | *
41 | *****************************************************************************/
42 |
43 | import UIKit
44 |
45 | class BaseViewController: UIViewController
46 | {
47 | required init(coder aDecoder: NSCoder) {
48 | fatalError("NSCoding not supported")
49 | }
50 |
51 | init() {
52 | super.init(nibName: nil, bundle: nil)
53 | setup()
54 | }
55 |
56 | override func loadView() {
57 | super.loadView()
58 |
59 | self.edgesForExtendedLayout = []
60 | self.extendedLayoutIncludesOpaqueBars = true
61 |
62 | self.view.backgroundColor = .white
63 | self.view.autoresizesSubviews = true
64 | self.view.autoresizingMask = [ .flexibleWidth, .flexibleHeight ]
65 | }
66 |
67 | func setup() {
68 | // actual contents of init(). subclass can override this.
69 | }
70 |
71 | override func viewDidLoad() {
72 | super.viewDidLoad()
73 | // Do any additional setup after loading the view, typically from a nib.
74 | }
75 |
76 | override func didReceiveMemoryWarning() {
77 | super.didReceiveMemoryWarning()
78 | // Dispose of any resources that can be recreated.
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/DataViewController.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: DataViewController.swift
4 | * DESCRIPTION: PageMenuKitDemo: Data View Controller
5 | * DATE: Mon, Jun 5 2017
6 | * UPDATED: Thu, Jun 8 2017
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | * $Id: AppDelegate.m,v 1.6 2017/04/12 09:59:00 kouichi Exp $
40 | *
41 | *****************************************************************************/
42 |
43 | import UIKit
44 |
45 | class DataViewController: BaseViewController
46 | {
47 | public private(set) var textLabel: UILabel? = nil
48 |
49 | override func setup() {
50 | super.setup()
51 |
52 | self.title = "Demo"
53 | }
54 |
55 | override func didReceiveMemoryWarning() {
56 | super.didReceiveMemoryWarning()
57 | // Dispose of any resources that can be recreated.
58 | }
59 |
60 | override func loadView() {
61 | super.loadView()
62 |
63 | let label = UILabel(frame: self.view.bounds)
64 | label.backgroundColor = UIColor.hexColor(0xccccff)
65 | label.font = UIFont.systemFont(ofSize: 64.0)
66 | label.textAlignment = .center
67 | label.adjustsFontSizeToFitWidth = true
68 | self.view.addSubview(label)
69 | self.textLabel = label
70 | }
71 |
72 | override func viewDidLoad() {
73 | super.viewDidLoad()
74 | }
75 |
76 | override func viewWillAppear(_ animated: Bool) {
77 | super.viewWillAppear(animated)
78 |
79 | self.textLabel?.text = self.title
80 |
81 | self.navigationController?.navigationBar.isHidden = true
82 | }
83 |
84 | override func viewWillDisappear(_ animated: Bool) {
85 | super.viewWillDisappear(animated)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 |
33 | UISupportedInterfaceOrientations~ipad
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationPortraitUpsideDown
37 | UIInterfaceOrientationLandscapeLeft
38 | UIInterfaceOrientationLandscapeRight
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/PageMenuKitDemo/RootViewController.swift:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | *
3 | * FILE: RootViewController.swift
4 | * DESCRIPTION: PageMenuKitDemo: Application Root View Controller
5 | * DATE: Fri, Jun 2 2017
6 | * UPDATED: Mon, Feb 18 2019
7 | * AUTHOR: Kouichi ABE (WALL) / 阿部康一
8 | * E-MAIL: kouichi@MagickWorX.COM
9 | * URL: http://www.MagickWorX.COM/
10 | * COPYRIGHT: (c) 2017-2019 阿部康一/Kouichi ABE (WALL), All rights reserved.
11 | * LICENSE:
12 | *
13 | * Copyright (c) 2017-2019 Kouichi ABE (WALL) ,
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions
18 | * are met:
19 | *
20 | * 1. Redistributions of source code must retain the above copyright
21 | * notice, this list of conditions and the following disclaimer.
22 | *
23 | * 2. Redistributions in binary form must reproduce the above copyright
24 | * notice, this list of conditions and the following disclaimer in the
25 | * documentation and/or other materials provided with the distribution.
26 | *
27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 | * THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | * $Id: AppDelegate.m,v 1.6 2017/04/12 09:59:00 kouichi Exp $
40 | *
41 | *****************************************************************************/
42 |
43 | import UIKit
44 | import PageMenuKit
45 |
46 | class RootViewController: BaseViewController
47 | {
48 | var pageMenuController: PMKPageMenuController? = nil
49 |
50 | override func setup() {
51 | super.setup()
52 |
53 | self.title = "PageMenuKit Frameworks"
54 | }
55 |
56 | override func didReceiveMemoryWarning() {
57 | super.didReceiveMemoryWarning()
58 | // Dispose of any resources that can be recreated.
59 | }
60 |
61 | override func loadView() {
62 | super.loadView()
63 | }
64 |
65 | override func viewDidLoad() {
66 | super.viewDidLoad()
67 |
68 | var controllers: [UIViewController] = []
69 | let dateFormatter = DateFormatter()
70 | for month in dateFormatter.monthSymbols {
71 | let viewController: DataViewController = DataViewController()
72 | viewController.title = month
73 | controllers.append(viewController)
74 | }
75 |
76 | let statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
77 | /*
78 | * Available menuStyles:
79 | * .plain, .tab, .smart, .hacka, .ellipse, .web, .suite, .netlab, .nhk
80 | * See PMKPageMenuItem.swift in PageMenuKit folder.
81 | * "menuColors: []" means that we will use the default colors.
82 | * "startIndex" can be set 1...controllers.count.
83 | */
84 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .smart, menuColors: [], startIndex: 1, topBarHeight: statusBarHeight)
85 | // pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .plain, menuColors: [.purple], startIndex: 8, topBarHeight: statusBarHeight)
86 | pageMenuController?.delegate = self
87 | self.addChild(pageMenuController!)
88 | self.view.addSubview(pageMenuController!.view)
89 | pageMenuController?.didMove(toParent: self)
90 | }
91 |
92 | override func viewWillAppear(_ animated: Bool) {
93 | super.viewWillAppear(animated)
94 |
95 | self.navigationController?.navigationBar.isHidden = false
96 | }
97 | }
98 |
99 | extension RootViewController: PMKPageMenuControllerDelegate
100 | {
101 | func pageMenuController(_ pageMenuController: PMKPageMenuController, willMoveTo viewController: UIViewController, at menuIndex: Int) {
102 | }
103 |
104 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didMoveTo viewController: UIViewController, at menuIndex: Int) {
105 | }
106 |
107 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didPrepare menuItems: [PMKPageMenuItem]) {
108 | // XXX: For .hacka style
109 | var i: Int = 1
110 | for item: PMKPageMenuItem in menuItems {
111 | item.badgeValue = String(format: "%zd", i)
112 | i += 1
113 | }
114 | }
115 |
116 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didSelect menuItem: PMKPageMenuItem, at menuIndex: Int) {
117 | menuItem.badgeValue = nil // XXX: For .hacka style
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/PageMenuKitSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXAggregateTarget section */
10 | B33FF34C258B2415004DBC52 /* PageMenuKitSwiftXCFramework */ = {
11 | isa = PBXAggregateTarget;
12 | buildConfigurationList = B33FF34F258B2415004DBC52 /* Build configuration list for PBXAggregateTarget "PageMenuKitSwiftXCFramework" */;
13 | buildPhases = (
14 | B33FF353258B2426004DBC52 /* ShellScript */,
15 | );
16 | dependencies = (
17 | );
18 | name = PageMenuKitSwiftXCFramework;
19 | productName = PageMenuKitSwiftXCFramework;
20 | };
21 | /* End PBXAggregateTarget section */
22 |
23 | /* Begin PBXBuildFile section */
24 | B3650E861EEA566500B3D2BB /* PMKPageMenuItemNHK.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3650E851EEA566500B3D2BB /* PMKPageMenuItemNHK.swift */; };
25 | B3FA139D23A2A86D00F1C379 /* PageMenuKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3FD5BAD1EE967A000842272 /* PageMenuKit.framework */; };
26 | B3FA139E23A2A86E00F1C379 /* PageMenuKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B3FD5BAD1EE967A000842272 /* PageMenuKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
27 | B3FD5BB11EE967A000842272 /* PageMenuKit.h in Headers */ = {isa = PBXBuildFile; fileRef = B3FD5BAF1EE967A000842272 /* PageMenuKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
28 | B3FD5BC71EE96AC100842272 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BC61EE96AC100842272 /* AppDelegate.swift */; };
29 | B3FD5BCE1EE96AC100842272 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B3FD5BCD1EE96AC100842272 /* Assets.xcassets */; };
30 | B3FD5BD11EE96AC100842272 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B3FD5BCF1EE96AC100842272 /* LaunchScreen.storyboard */; };
31 | B3FD5BE11EE96B1500842272 /* PMKPageMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BD61EE96B1500842272 /* PMKPageMenuController.swift */; };
32 | B3FD5BE21EE96B1500842272 /* PMKPageMenuControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BD71EE96B1500842272 /* PMKPageMenuControllerDelegate.swift */; };
33 | B3FD5BE31EE96B1500842272 /* PMKPageMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BD81EE96B1500842272 /* PMKPageMenuItem.swift */; };
34 | B3FD5BE41EE96B1500842272 /* PMKPageMenuItemEllipse.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BD91EE96B1500842272 /* PMKPageMenuItemEllipse.swift */; };
35 | B3FD5BE51EE96B1500842272 /* PMKPageMenuItemHacka.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDA1EE96B1500842272 /* PMKPageMenuItemHacka.swift */; };
36 | B3FD5BE61EE96B1500842272 /* PMKPageMenuItemNetLab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDB1EE96B1500842272 /* PMKPageMenuItemNetLab.swift */; };
37 | B3FD5BE71EE96B1500842272 /* PMKPageMenuItemPlain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDC1EE96B1500842272 /* PMKPageMenuItemPlain.swift */; };
38 | B3FD5BE81EE96B1500842272 /* PMKPageMenuItemSmart.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDD1EE96B1500842272 /* PMKPageMenuItemSmart.swift */; };
39 | B3FD5BE91EE96B1500842272 /* PMKPageMenuItemSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDE1EE96B1500842272 /* PMKPageMenuItemSuite.swift */; };
40 | B3FD5BEA1EE96B1500842272 /* PMKPageMenuItemTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BDF1EE96B1500842272 /* PMKPageMenuItemTab.swift */; };
41 | B3FD5BEB1EE96B1500842272 /* PMKPageMenuItemWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BE01EE96B1500842272 /* PMKPageMenuItemWeb.swift */; };
42 | B3FD5BED1EE96DE100842272 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BEC1EE96DE100842272 /* BaseViewController.swift */; };
43 | B3FD5BEF1EE96DE800842272 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BEE1EE96DE800842272 /* RootViewController.swift */; };
44 | B3FD5BF11EE96DEF00842272 /* DataViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FD5BF01EE96DEF00842272 /* DataViewController.swift */; };
45 | /* End PBXBuildFile section */
46 |
47 | /* Begin PBXContainerItemProxy section */
48 | B3650E871EEA797500B3D2BB /* PBXContainerItemProxy */ = {
49 | isa = PBXContainerItemProxy;
50 | containerPortal = B3FD5B8B1EE966FB00842272 /* Project object */;
51 | proxyType = 1;
52 | remoteGlobalIDString = B3FD5BAC1EE967A000842272;
53 | remoteInfo = PageMenuKit;
54 | };
55 | /* End PBXContainerItemProxy section */
56 |
57 | /* Begin PBXCopyFilesBuildPhase section */
58 | B3FA139F23A2A86E00F1C379 /* Embed Frameworks */ = {
59 | isa = PBXCopyFilesBuildPhase;
60 | buildActionMask = 2147483647;
61 | dstPath = "";
62 | dstSubfolderSpec = 10;
63 | files = (
64 | B3FA139E23A2A86E00F1C379 /* PageMenuKit.framework in Embed Frameworks */,
65 | );
66 | name = "Embed Frameworks";
67 | runOnlyForDeploymentPostprocessing = 0;
68 | };
69 | /* End PBXCopyFilesBuildPhase section */
70 |
71 | /* Begin PBXFileReference section */
72 | B3650E851EEA566500B3D2BB /* PMKPageMenuItemNHK.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemNHK.swift; sourceTree = ""; };
73 | B3FD5BAD1EE967A000842272 /* PageMenuKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PageMenuKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74 | B3FD5BAF1EE967A000842272 /* PageMenuKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PageMenuKit.h; sourceTree = ""; };
75 | B3FD5BB01EE967A000842272 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
76 | B3FD5BC41EE96AC000842272 /* PageMenuKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PageMenuKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
77 | B3FD5BC61EE96AC100842272 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
78 | B3FD5BCD1EE96AC100842272 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
79 | B3FD5BD01EE96AC100842272 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
80 | B3FD5BD21EE96AC100842272 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
81 | B3FD5BD61EE96B1500842272 /* PMKPageMenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuController.swift; sourceTree = ""; };
82 | B3FD5BD71EE96B1500842272 /* PMKPageMenuControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuControllerDelegate.swift; sourceTree = ""; };
83 | B3FD5BD81EE96B1500842272 /* PMKPageMenuItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItem.swift; sourceTree = ""; };
84 | B3FD5BD91EE96B1500842272 /* PMKPageMenuItemEllipse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemEllipse.swift; sourceTree = ""; };
85 | B3FD5BDA1EE96B1500842272 /* PMKPageMenuItemHacka.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemHacka.swift; sourceTree = ""; };
86 | B3FD5BDB1EE96B1500842272 /* PMKPageMenuItemNetLab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemNetLab.swift; sourceTree = ""; };
87 | B3FD5BDC1EE96B1500842272 /* PMKPageMenuItemPlain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemPlain.swift; sourceTree = ""; };
88 | B3FD5BDD1EE96B1500842272 /* PMKPageMenuItemSmart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemSmart.swift; sourceTree = ""; };
89 | B3FD5BDE1EE96B1500842272 /* PMKPageMenuItemSuite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemSuite.swift; sourceTree = ""; };
90 | B3FD5BDF1EE96B1500842272 /* PMKPageMenuItemTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemTab.swift; sourceTree = ""; };
91 | B3FD5BE01EE96B1500842272 /* PMKPageMenuItemWeb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMKPageMenuItemWeb.swift; sourceTree = ""; };
92 | B3FD5BEC1EE96DE100842272 /* BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; };
93 | B3FD5BEE1EE96DE800842272 /* RootViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; };
94 | B3FD5BF01EE96DEF00842272 /* DataViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataViewController.swift; sourceTree = ""; };
95 | /* End PBXFileReference section */
96 |
97 | /* Begin PBXFrameworksBuildPhase section */
98 | B3FD5BA91EE967A000842272 /* Frameworks */ = {
99 | isa = PBXFrameworksBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | );
103 | runOnlyForDeploymentPostprocessing = 0;
104 | };
105 | B3FD5BC11EE96AC000842272 /* Frameworks */ = {
106 | isa = PBXFrameworksBuildPhase;
107 | buildActionMask = 2147483647;
108 | files = (
109 | B3FA139D23A2A86D00F1C379 /* PageMenuKit.framework in Frameworks */,
110 | );
111 | runOnlyForDeploymentPostprocessing = 0;
112 | };
113 | /* End PBXFrameworksBuildPhase section */
114 |
115 | /* Begin PBXGroup section */
116 | B3FD5B8A1EE966FB00842272 = {
117 | isa = PBXGroup;
118 | children = (
119 | B3FD5BAE1EE967A000842272 /* PageMenuKit */,
120 | B3FD5BC51EE96AC000842272 /* PageMenuKitDemo */,
121 | B3FD5B941EE966FB00842272 /* Products */,
122 | );
123 | sourceTree = "";
124 | };
125 | B3FD5B941EE966FB00842272 /* Products */ = {
126 | isa = PBXGroup;
127 | children = (
128 | B3FD5BAD1EE967A000842272 /* PageMenuKit.framework */,
129 | B3FD5BC41EE96AC000842272 /* PageMenuKitDemo.app */,
130 | );
131 | name = Products;
132 | sourceTree = "";
133 | };
134 | B3FD5BAE1EE967A000842272 /* PageMenuKit */ = {
135 | isa = PBXGroup;
136 | children = (
137 | B3650E851EEA566500B3D2BB /* PMKPageMenuItemNHK.swift */,
138 | B3FD5BD61EE96B1500842272 /* PMKPageMenuController.swift */,
139 | B3FD5BD71EE96B1500842272 /* PMKPageMenuControllerDelegate.swift */,
140 | B3FD5BD81EE96B1500842272 /* PMKPageMenuItem.swift */,
141 | B3FD5BD91EE96B1500842272 /* PMKPageMenuItemEllipse.swift */,
142 | B3FD5BDA1EE96B1500842272 /* PMKPageMenuItemHacka.swift */,
143 | B3FD5BDB1EE96B1500842272 /* PMKPageMenuItemNetLab.swift */,
144 | B3FD5BDC1EE96B1500842272 /* PMKPageMenuItemPlain.swift */,
145 | B3FD5BDD1EE96B1500842272 /* PMKPageMenuItemSmart.swift */,
146 | B3FD5BDE1EE96B1500842272 /* PMKPageMenuItemSuite.swift */,
147 | B3FD5BDF1EE96B1500842272 /* PMKPageMenuItemTab.swift */,
148 | B3FD5BE01EE96B1500842272 /* PMKPageMenuItemWeb.swift */,
149 | B3FD5BAF1EE967A000842272 /* PageMenuKit.h */,
150 | B3FD5BB01EE967A000842272 /* Info.plist */,
151 | );
152 | path = PageMenuKit;
153 | sourceTree = "";
154 | };
155 | B3FD5BC51EE96AC000842272 /* PageMenuKitDemo */ = {
156 | isa = PBXGroup;
157 | children = (
158 | B3FD5BF01EE96DEF00842272 /* DataViewController.swift */,
159 | B3FD5BEE1EE96DE800842272 /* RootViewController.swift */,
160 | B3FD5BEC1EE96DE100842272 /* BaseViewController.swift */,
161 | B3FD5BC61EE96AC100842272 /* AppDelegate.swift */,
162 | B3FD5BCD1EE96AC100842272 /* Assets.xcassets */,
163 | B3FD5BCF1EE96AC100842272 /* LaunchScreen.storyboard */,
164 | B3FD5BD21EE96AC100842272 /* Info.plist */,
165 | );
166 | path = PageMenuKitDemo;
167 | sourceTree = "";
168 | };
169 | /* End PBXGroup section */
170 |
171 | /* Begin PBXHeadersBuildPhase section */
172 | B3FD5BAA1EE967A000842272 /* Headers */ = {
173 | isa = PBXHeadersBuildPhase;
174 | buildActionMask = 2147483647;
175 | files = (
176 | B3FD5BB11EE967A000842272 /* PageMenuKit.h in Headers */,
177 | );
178 | runOnlyForDeploymentPostprocessing = 0;
179 | };
180 | /* End PBXHeadersBuildPhase section */
181 |
182 | /* Begin PBXNativeTarget section */
183 | B3FD5BAC1EE967A000842272 /* PageMenuKit */ = {
184 | isa = PBXNativeTarget;
185 | buildConfigurationList = B3FD5BB61EE967A000842272 /* Build configuration list for PBXNativeTarget "PageMenuKit" */;
186 | buildPhases = (
187 | B3FD5BA81EE967A000842272 /* Sources */,
188 | B3FD5BA91EE967A000842272 /* Frameworks */,
189 | B3FD5BAA1EE967A000842272 /* Headers */,
190 | B3FD5BAB1EE967A000842272 /* Resources */,
191 | );
192 | buildRules = (
193 | );
194 | dependencies = (
195 | );
196 | name = PageMenuKit;
197 | productName = PageMenuKit;
198 | productReference = B3FD5BAD1EE967A000842272 /* PageMenuKit.framework */;
199 | productType = "com.apple.product-type.framework";
200 | };
201 | B3FD5BC31EE96AC000842272 /* PageMenuKitDemo */ = {
202 | isa = PBXNativeTarget;
203 | buildConfigurationList = B3FD5BD31EE96AC100842272 /* Build configuration list for PBXNativeTarget "PageMenuKitDemo" */;
204 | buildPhases = (
205 | B3FD5BC01EE96AC000842272 /* Sources */,
206 | B3FD5BC11EE96AC000842272 /* Frameworks */,
207 | B3FD5BC21EE96AC000842272 /* Resources */,
208 | B3FA139F23A2A86E00F1C379 /* Embed Frameworks */,
209 | );
210 | buildRules = (
211 | );
212 | dependencies = (
213 | B3650E881EEA797500B3D2BB /* PBXTargetDependency */,
214 | );
215 | name = PageMenuKitDemo;
216 | productName = PageMenuKitDemo;
217 | productReference = B3FD5BC41EE96AC000842272 /* PageMenuKitDemo.app */;
218 | productType = "com.apple.product-type.application";
219 | };
220 | /* End PBXNativeTarget section */
221 |
222 | /* Begin PBXProject section */
223 | B3FD5B8B1EE966FB00842272 /* Project object */ = {
224 | isa = PBXProject;
225 | attributes = {
226 | LastSwiftUpdateCheck = 0830;
227 | LastUpgradeCheck = 1020;
228 | ORGANIZATIONNAME = "Kouichi ABE (WALL)";
229 | TargetAttributes = {
230 | B33FF34C258B2415004DBC52 = {
231 | CreatedOnToolsVersion = 12.3;
232 | ProvisioningStyle = Automatic;
233 | };
234 | B3FD5BAC1EE967A000842272 = {
235 | CreatedOnToolsVersion = 8.3.2;
236 | LastSwiftMigration = 0830;
237 | ProvisioningStyle = Automatic;
238 | };
239 | B3FD5BC31EE96AC000842272 = {
240 | CreatedOnToolsVersion = 8.3.2;
241 | ProvisioningStyle = Automatic;
242 | };
243 | };
244 | };
245 | buildConfigurationList = B3FD5B8E1EE966FB00842272 /* Build configuration list for PBXProject "PageMenuKitSwift" */;
246 | compatibilityVersion = "Xcode 3.2";
247 | developmentRegion = en;
248 | hasScannedForEncodings = 0;
249 | knownRegions = (
250 | en,
251 | Base,
252 | );
253 | mainGroup = B3FD5B8A1EE966FB00842272;
254 | productRefGroup = B3FD5B941EE966FB00842272 /* Products */;
255 | projectDirPath = "";
256 | projectRoot = "";
257 | targets = (
258 | B3FD5BAC1EE967A000842272 /* PageMenuKit */,
259 | B3FD5BC31EE96AC000842272 /* PageMenuKitDemo */,
260 | B33FF34C258B2415004DBC52 /* PageMenuKitSwiftXCFramework */,
261 | );
262 | };
263 | /* End PBXProject section */
264 |
265 | /* Begin PBXResourcesBuildPhase section */
266 | B3FD5BAB1EE967A000842272 /* Resources */ = {
267 | isa = PBXResourcesBuildPhase;
268 | buildActionMask = 2147483647;
269 | files = (
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | };
273 | B3FD5BC21EE96AC000842272 /* Resources */ = {
274 | isa = PBXResourcesBuildPhase;
275 | buildActionMask = 2147483647;
276 | files = (
277 | B3FD5BD11EE96AC100842272 /* LaunchScreen.storyboard in Resources */,
278 | B3FD5BCE1EE96AC100842272 /* Assets.xcassets in Resources */,
279 | );
280 | runOnlyForDeploymentPostprocessing = 0;
281 | };
282 | /* End PBXResourcesBuildPhase section */
283 |
284 | /* Begin PBXShellScriptBuildPhase section */
285 | B33FF353258B2426004DBC52 /* ShellScript */ = {
286 | isa = PBXShellScriptBuildPhase;
287 | buildActionMask = 2147483647;
288 | files = (
289 | );
290 | inputFileListPaths = (
291 | );
292 | inputPaths = (
293 | );
294 | outputFileListPaths = (
295 | );
296 | outputPaths = (
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | shellPath = /bin/sh;
300 | shellScript = "#!/bin/sh\n\nOUTPUT_FOLDER=${BUILD_DIR}/${CONFIGURATION}-xcframework\n\nARCHS_IOS=\"arm64\"\nARCHS_SIMULATOR=\"x86_64\"\n\nSCHEME_NAME=\"PageMenuKit\"\n\n# make sure the output directory exists\nmkdir -p \"${OUTPUT_FOLDER}\"\n\n# Step 1. Archive Device and Simulator versions\nmk_archive() {\n archs=$1\n platform=$2\n output=$3\n\n xcodebuild \\\n ENABLE_BITCODE=YES \\\n BITCODE_GENERATION_MODE=bitcode \\\n OTHER_CFLAGS=\"-fembed-bitcode\" \\\n BUILD_LIBRARY_FOR_DISTRIBUTION=YES \\\n SKIP_INSTALL=NO \\\n ONLY_ACTIVE_ARCH=YES \\\n ARCHS=\"${archs}\" \\\n -project \"${PROJECT_NAME}.xcodeproj\" \\\n -configuration \"${CONFIGURATION}\" \\\n -scheme \"${SCHEME_NAME}\" \\\n -destination \"generic/platform=${platform}\" \\\n -archivePath \"${OUTPUT_FOLDER}/${PROJECT_NAME}-${output}\" \\\n archive\n}\n\nmk_archive ${ARCHS_IOS} \"iOS\" \"iOS\"\nmk_archive ${ARCHS_SIMULATOR} \"iOS Simulator\" \"iOS_Simulator\"\n\n# Step 2. Create xcframework with all frameworks\nxcodebuild \\\n-create-xcframework \\\n-framework \"${OUTPUT_FOLDER}/${PROJECT_NAME}-iOS.xcarchive/Products/Library/Frameworks/${SCHEME_NAME}.framework\" \\\n-framework \"${OUTPUT_FOLDER}/${PROJECT_NAME}-iOS_Simulator.xcarchive/Products/Library/Frameworks/${SCHEME_NAME}.framework\" \\\n-output \"${OUTPUT_FOLDER}/${SCHEME_NAME}.xcframework\"\n\n# Step 3. Convenience step to open the output's directory in Finder\nopen \"${OUTPUT_FOLDER}\"\n";
301 | };
302 | /* End PBXShellScriptBuildPhase section */
303 |
304 | /* Begin PBXSourcesBuildPhase section */
305 | B3FD5BA81EE967A000842272 /* Sources */ = {
306 | isa = PBXSourcesBuildPhase;
307 | buildActionMask = 2147483647;
308 | files = (
309 | B3FD5BE11EE96B1500842272 /* PMKPageMenuController.swift in Sources */,
310 | B3FD5BE71EE96B1500842272 /* PMKPageMenuItemPlain.swift in Sources */,
311 | B3FD5BE61EE96B1500842272 /* PMKPageMenuItemNetLab.swift in Sources */,
312 | B3FD5BEB1EE96B1500842272 /* PMKPageMenuItemWeb.swift in Sources */,
313 | B3FD5BEA1EE96B1500842272 /* PMKPageMenuItemTab.swift in Sources */,
314 | B3FD5BE21EE96B1500842272 /* PMKPageMenuControllerDelegate.swift in Sources */,
315 | B3FD5BE41EE96B1500842272 /* PMKPageMenuItemEllipse.swift in Sources */,
316 | B3FD5BE81EE96B1500842272 /* PMKPageMenuItemSmart.swift in Sources */,
317 | B3FD5BE31EE96B1500842272 /* PMKPageMenuItem.swift in Sources */,
318 | B3650E861EEA566500B3D2BB /* PMKPageMenuItemNHK.swift in Sources */,
319 | B3FD5BE91EE96B1500842272 /* PMKPageMenuItemSuite.swift in Sources */,
320 | B3FD5BE51EE96B1500842272 /* PMKPageMenuItemHacka.swift in Sources */,
321 | );
322 | runOnlyForDeploymentPostprocessing = 0;
323 | };
324 | B3FD5BC01EE96AC000842272 /* Sources */ = {
325 | isa = PBXSourcesBuildPhase;
326 | buildActionMask = 2147483647;
327 | files = (
328 | B3FD5BF11EE96DEF00842272 /* DataViewController.swift in Sources */,
329 | B3FD5BC71EE96AC100842272 /* AppDelegate.swift in Sources */,
330 | B3FD5BED1EE96DE100842272 /* BaseViewController.swift in Sources */,
331 | B3FD5BEF1EE96DE800842272 /* RootViewController.swift in Sources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | /* End PBXSourcesBuildPhase section */
336 |
337 | /* Begin PBXTargetDependency section */
338 | B3650E881EEA797500B3D2BB /* PBXTargetDependency */ = {
339 | isa = PBXTargetDependency;
340 | target = B3FD5BAC1EE967A000842272 /* PageMenuKit */;
341 | targetProxy = B3650E871EEA797500B3D2BB /* PBXContainerItemProxy */;
342 | };
343 | /* End PBXTargetDependency section */
344 |
345 | /* Begin PBXVariantGroup section */
346 | B3FD5BCF1EE96AC100842272 /* LaunchScreen.storyboard */ = {
347 | isa = PBXVariantGroup;
348 | children = (
349 | B3FD5BD01EE96AC100842272 /* Base */,
350 | );
351 | name = LaunchScreen.storyboard;
352 | sourceTree = "";
353 | };
354 | /* End PBXVariantGroup section */
355 |
356 | /* Begin XCBuildConfiguration section */
357 | B33FF34D258B2415004DBC52 /* Debug */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | CODE_SIGN_STYLE = Automatic;
361 | PRODUCT_NAME = "$(TARGET_NAME)";
362 | };
363 | name = Debug;
364 | };
365 | B33FF34E258B2415004DBC52 /* Release */ = {
366 | isa = XCBuildConfiguration;
367 | buildSettings = {
368 | CODE_SIGN_STYLE = Automatic;
369 | PRODUCT_NAME = "$(TARGET_NAME)";
370 | };
371 | name = Release;
372 | };
373 | B3FD5BA31EE966FC00842272 /* Debug */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | ALWAYS_SEARCH_USER_PATHS = NO;
377 | CLANG_ANALYZER_NONNULL = YES;
378 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
379 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
380 | CLANG_CXX_LIBRARY = "libc++";
381 | CLANG_ENABLE_MODULES = YES;
382 | CLANG_ENABLE_OBJC_ARC = YES;
383 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
384 | CLANG_WARN_BOOL_CONVERSION = YES;
385 | CLANG_WARN_COMMA = YES;
386 | CLANG_WARN_CONSTANT_CONVERSION = YES;
387 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
389 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
390 | CLANG_WARN_EMPTY_BODY = YES;
391 | CLANG_WARN_ENUM_CONVERSION = YES;
392 | CLANG_WARN_INFINITE_RECURSION = YES;
393 | CLANG_WARN_INT_CONVERSION = YES;
394 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
395 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
396 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
397 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
398 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
399 | CLANG_WARN_STRICT_PROTOTYPES = YES;
400 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
401 | CLANG_WARN_UNREACHABLE_CODE = YES;
402 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
403 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
404 | COPY_PHASE_STRIP = NO;
405 | DEBUG_INFORMATION_FORMAT = dwarf;
406 | ENABLE_STRICT_OBJC_MSGSEND = YES;
407 | ENABLE_TESTABILITY = YES;
408 | GCC_C_LANGUAGE_STANDARD = gnu99;
409 | GCC_DYNAMIC_NO_PIC = NO;
410 | GCC_NO_COMMON_BLOCKS = YES;
411 | GCC_OPTIMIZATION_LEVEL = 0;
412 | GCC_PREPROCESSOR_DEFINITIONS = (
413 | "DEBUG=1",
414 | "$(inherited)",
415 | );
416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
418 | GCC_WARN_UNDECLARED_SELECTOR = YES;
419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
420 | GCC_WARN_UNUSED_FUNCTION = YES;
421 | GCC_WARN_UNUSED_VARIABLE = YES;
422 | IPHONEOS_DEPLOYMENT_TARGET = 13.6;
423 | MTL_ENABLE_DEBUG_INFO = YES;
424 | ONLY_ACTIVE_ARCH = YES;
425 | SDKROOT = iphoneos;
426 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
427 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
428 | TARGETED_DEVICE_FAMILY = "1,2";
429 | };
430 | name = Debug;
431 | };
432 | B3FD5BA41EE966FC00842272 /* Release */ = {
433 | isa = XCBuildConfiguration;
434 | buildSettings = {
435 | ALWAYS_SEARCH_USER_PATHS = NO;
436 | CLANG_ANALYZER_NONNULL = YES;
437 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
438 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
439 | CLANG_CXX_LIBRARY = "libc++";
440 | CLANG_ENABLE_MODULES = YES;
441 | CLANG_ENABLE_OBJC_ARC = YES;
442 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
443 | CLANG_WARN_BOOL_CONVERSION = YES;
444 | CLANG_WARN_COMMA = YES;
445 | CLANG_WARN_CONSTANT_CONVERSION = YES;
446 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
447 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
448 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
449 | CLANG_WARN_EMPTY_BODY = YES;
450 | CLANG_WARN_ENUM_CONVERSION = YES;
451 | CLANG_WARN_INFINITE_RECURSION = YES;
452 | CLANG_WARN_INT_CONVERSION = YES;
453 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
454 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
455 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
456 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
457 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
458 | CLANG_WARN_STRICT_PROTOTYPES = YES;
459 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
460 | CLANG_WARN_UNREACHABLE_CODE = YES;
461 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
462 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
463 | COPY_PHASE_STRIP = NO;
464 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
465 | ENABLE_NS_ASSERTIONS = NO;
466 | ENABLE_STRICT_OBJC_MSGSEND = YES;
467 | GCC_C_LANGUAGE_STANDARD = gnu99;
468 | GCC_NO_COMMON_BLOCKS = YES;
469 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
470 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
471 | GCC_WARN_UNDECLARED_SELECTOR = YES;
472 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
473 | GCC_WARN_UNUSED_FUNCTION = YES;
474 | GCC_WARN_UNUSED_VARIABLE = YES;
475 | IPHONEOS_DEPLOYMENT_TARGET = 13.6;
476 | MTL_ENABLE_DEBUG_INFO = NO;
477 | SDKROOT = iphoneos;
478 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
479 | TARGETED_DEVICE_FAMILY = "1,2";
480 | VALIDATE_PRODUCT = YES;
481 | };
482 | name = Release;
483 | };
484 | B3FD5BB71EE967A000842272 /* Debug */ = {
485 | isa = XCBuildConfiguration;
486 | buildSettings = {
487 | CLANG_ENABLE_MODULES = YES;
488 | CODE_SIGN_IDENTITY = "";
489 | CURRENT_PROJECT_VERSION = 2;
490 | DEFINES_MODULE = YES;
491 | DEVELOPMENT_TEAM = "";
492 | DYLIB_COMPATIBILITY_VERSION = 1;
493 | DYLIB_CURRENT_VERSION = 1;
494 | DYLIB_INSTALL_NAME_BASE = "@rpath";
495 | INFOPLIST_FILE = PageMenuKit/Info.plist;
496 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
497 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
499 | ONLY_ACTIVE_ARCH = NO;
500 | PRODUCT_BUNDLE_IDENTIFIER = com.magickworx.PageMenuKit;
501 | PRODUCT_NAME = "$(TARGET_NAME)";
502 | SKIP_INSTALL = YES;
503 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
504 | SWIFT_VERSION = 5.0;
505 | VALID_ARCHS = "$(ARCHS_STANDARD_64_BIT)";
506 | VERSIONING_SYSTEM = "apple-generic";
507 | VERSION_INFO_PREFIX = "";
508 | };
509 | name = Debug;
510 | };
511 | B3FD5BB81EE967A000842272 /* Release */ = {
512 | isa = XCBuildConfiguration;
513 | buildSettings = {
514 | CLANG_ENABLE_MODULES = YES;
515 | CODE_SIGN_IDENTITY = "";
516 | CURRENT_PROJECT_VERSION = 2;
517 | DEFINES_MODULE = YES;
518 | DEVELOPMENT_TEAM = "";
519 | DYLIB_COMPATIBILITY_VERSION = 1;
520 | DYLIB_CURRENT_VERSION = 1;
521 | DYLIB_INSTALL_NAME_BASE = "@rpath";
522 | INFOPLIST_FILE = PageMenuKit/Info.plist;
523 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
524 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
526 | ONLY_ACTIVE_ARCH = NO;
527 | PRODUCT_BUNDLE_IDENTIFIER = com.magickworx.PageMenuKit;
528 | PRODUCT_NAME = "$(TARGET_NAME)";
529 | SKIP_INSTALL = YES;
530 | SWIFT_VERSION = 5.0;
531 | VALID_ARCHS = "$(ARCHS_STANDARD_64_BIT)";
532 | VERSIONING_SYSTEM = "apple-generic";
533 | VERSION_INFO_PREFIX = "";
534 | };
535 | name = Release;
536 | };
537 | B3FD5BD41EE96AC100842272 /* Debug */ = {
538 | isa = XCBuildConfiguration;
539 | buildSettings = {
540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
541 | DEVELOPMENT_TEAM = "";
542 | INFOPLIST_FILE = PageMenuKitDemo/Info.plist;
543 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
545 | PRODUCT_BUNDLE_IDENTIFIER = com.magickworx.PageMenuKitDemo;
546 | PRODUCT_NAME = "$(TARGET_NAME)";
547 | SWIFT_VERSION = 5.0;
548 | VALID_ARCHS = "$(ARCHS_STANDARD_64_BIT)";
549 | };
550 | name = Debug;
551 | };
552 | B3FD5BD51EE96AC100842272 /* Release */ = {
553 | isa = XCBuildConfiguration;
554 | buildSettings = {
555 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
556 | DEVELOPMENT_TEAM = "";
557 | INFOPLIST_FILE = PageMenuKitDemo/Info.plist;
558 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
559 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
560 | PRODUCT_BUNDLE_IDENTIFIER = com.magickworx.PageMenuKitDemo;
561 | PRODUCT_NAME = "$(TARGET_NAME)";
562 | SWIFT_VERSION = 5.0;
563 | VALID_ARCHS = "$(ARCHS_STANDARD_64_BIT)";
564 | };
565 | name = Release;
566 | };
567 | /* End XCBuildConfiguration section */
568 |
569 | /* Begin XCConfigurationList section */
570 | B33FF34F258B2415004DBC52 /* Build configuration list for PBXAggregateTarget "PageMenuKitSwiftXCFramework" */ = {
571 | isa = XCConfigurationList;
572 | buildConfigurations = (
573 | B33FF34D258B2415004DBC52 /* Debug */,
574 | B33FF34E258B2415004DBC52 /* Release */,
575 | );
576 | defaultConfigurationIsVisible = 0;
577 | defaultConfigurationName = Release;
578 | };
579 | B3FD5B8E1EE966FB00842272 /* Build configuration list for PBXProject "PageMenuKitSwift" */ = {
580 | isa = XCConfigurationList;
581 | buildConfigurations = (
582 | B3FD5BA31EE966FC00842272 /* Debug */,
583 | B3FD5BA41EE966FC00842272 /* Release */,
584 | );
585 | defaultConfigurationIsVisible = 0;
586 | defaultConfigurationName = Release;
587 | };
588 | B3FD5BB61EE967A000842272 /* Build configuration list for PBXNativeTarget "PageMenuKit" */ = {
589 | isa = XCConfigurationList;
590 | buildConfigurations = (
591 | B3FD5BB71EE967A000842272 /* Debug */,
592 | B3FD5BB81EE967A000842272 /* Release */,
593 | );
594 | defaultConfigurationIsVisible = 0;
595 | defaultConfigurationName = Release;
596 | };
597 | B3FD5BD31EE96AC100842272 /* Build configuration list for PBXNativeTarget "PageMenuKitDemo" */ = {
598 | isa = XCConfigurationList;
599 | buildConfigurations = (
600 | B3FD5BD41EE96AC100842272 /* Debug */,
601 | B3FD5BD51EE96AC100842272 /* Release */,
602 | );
603 | defaultConfigurationIsVisible = 0;
604 | defaultConfigurationName = Release;
605 | };
606 | /* End XCConfigurationList section */
607 | };
608 | rootObject = B3FD5B8B1EE966FB00842272 /* Project object */;
609 | }
610 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PageMenuKitSwift
2 |
3 | [PageMenuController](https://github.com/magickworx/PageMenuController) の Swift 版。
4 |
5 | 日本のニュース系アプリで使われている横スクロールのメニュー画面とそのコンテンツを表示するユーザインタフェースのクラス。
6 | Xcode のプロジェクト一式を登録してあるので、実行すればシミュレータ上で動作確認が可能。
7 |
8 | Swift で実装し直す際に、汎用的で拡張しやすいようにクラスを再設計した。ページメニューの見た目だけが違うので、スタイルごとに PMKPageMenuItem のサブクラスを実装し、それを利用する仕組みにした。よって、簡単にカスタムメニューを追加できる。
9 |
10 | ## How to use PageMenuKit.framework
11 |
12 | Xcode の Build Target に PageMenuKitXCFramework を指定して Build を実行すると、PageMenuKit.xcframework が作成される。これを自作アプリの Xcode の Project で設定する。
13 |
14 | あとは、以下のようなコードを記述して利用する。
15 |
16 | ```Swift
17 | class RootViewController: UIViewController
18 | {
19 | var pageMenuController: PMKPageMenuController? = nil
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 |
24 | var controllers: [UIViewController] = []
25 | let dateFormatter = DateFormatter()
26 | for month in dateFormatter.monthSymbols {
27 | let viewController: DataViewController = DataViewController()
28 | viewController.title = month
29 | controllers.append(viewController)
30 | }
31 |
32 | let statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
33 | /*
34 | * Available menu styles:
35 | * .plain, .tab, .smart, .hacka, .ellipse, .web, .suite, .netlab and .nhk
36 | * See PMKPageMenuItem.swift in PageMenuKit folder.
37 | *
38 | * menuColors: [] means that we will use the default colors
39 | * "startIndex" can be set 1...controllers.count.
40 | */
41 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .smart, menuColors: [], startIndex: 1, topBarHeight: statusBarHeight)
42 | self.addChild(pageMenuController!)
43 | self.view.addSubview(pageMenuController!.view)
44 | pageMenuController?.didMove(toParent: self)
45 | }
46 | }
47 | ```
48 |
49 | より詳細なコードは PageMenuKitDemo 内の RootViewController.swift を見てね。
50 |
51 |
52 | ## Available Menu Styles
53 |
54 | ### .plain
55 | [ニュースパス](https://itunes.apple.com/jp/app/id1106788059?mt=8) っぽいメニュー画面
56 |
57 | 
58 |
59 | ### .tab
60 | [グノシー](https://itunes.apple.com/jp/app/id590384791?mt=8) っぽいメニュー画面
61 |
62 | 
63 |
64 | ### .smart
65 | [SmartNews](https://itunes.apple.com/jp/app/id579581125?mt=8) っぽいメニュー画面
66 |
67 | 
68 |
69 | ### .hacka
70 | [ハッカドール](https://itunes.apple.com/jp/app/id888231424?mt=8) っぽいメニュー画面
71 |
72 | 
73 |
74 | ### .ellipse
75 | [JCnews](https://itunes.apple.com/jp/app/id1024341813?mt=8) っぽいメニュー画面
76 |
77 | 
78 |
79 | ### .web
80 | [JCnews のウェブサイト](https://jcnews.tokyo/) っぽいメニュー画面
81 |
82 | 
83 |
84 | ### .suite
85 | [NewsSuite](https://itunes.apple.com/jp/app/id1176431318?mt=8) っぽいメニュー画面(背景色はグラデーション)
86 |
87 | ")
88 |
89 | ### .netlab
90 | [ねとらぼ](https://itunes.apple.com/jp/app/id949325541?mt=8) っぽいメニュー画面(背景色は透明)
91 |
92 | 
93 |
94 | ### .nhk
95 | [NHK ニュース・防災](https://itunes.apple.com/jp/app/id1121104608?mt=8) っぽいメニュー画面
96 |
97 | 
98 |
99 |
100 | ## Examples
101 |
102 | PMKPageMenuController の initializer の menuColors に __[]__ を指定するとデフォルトの配色になる。ここでは、各スタイルごとに色を変更する例を示す。
103 |
104 | ### .plain, .hacka, .ellipse, .nhk
105 |
106 | .plain, .hacka, .ellipse, .nhk の各スタイルで指定できる色は一つだけである。
107 | 以下の例では .plain スタイルに __紫(.purple)__ を設定している。
108 |
109 | ```swift
110 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .plain, menuColors: [ .purple ], topBarHeight: statusBarHeight)
111 | ```
112 | #### .plain
113 |
114 | 
115 |
116 | #### .hacka
117 |
118 | 
119 |
120 | #### .ellipse
121 |
122 | 
123 |
124 | #### .nhk
125 |
126 | 
127 |
128 |
129 | ### .tab, .smart
130 |
131 | .tab, .smart スタイルで指定できる色は一つ以上である。
132 | 以下の例では .tab スタイルに __赤、橙、黄、緑、青、紫__ を設定している。
133 | メニューの数が配色した数よりも多い場合は、順に色が適用される。
134 |
135 | ```swift
136 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .tab, menuColors: [ .red, .orange, .yello, .green, .blue, .purple ], topBarHeight: statusBarHeight)
137 | ```
138 |
139 | #### .tab
140 |
141 | 
142 |
143 | #### .smart
144 |
145 | 
146 |
147 |
148 | ### .web
149 |
150 | .web スタイルも .tab, .smart スタイルと同様に指定できる色は一つ以上である。
151 | ただし、背景色は現在固定されている。
152 | また、現実装では最初に指定した色が境界線の色になる。
153 |
154 | 以下の例では .web スタイルに __赤、橙、黄、緑、青、紫__ を設定している。
155 | メニューの数が配色した数よりも多い場合は、順に色が適用される。
156 |
157 | ```swift
158 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .web, menuColors: [ .red, .orange, .yello, .green, .blue, .purple ], topBarHeight: statusBarHeight)
159 | ```
160 |
161 | 
162 |
163 |
164 | ### .suite
165 |
166 | .suite スタイルで指定できる色は一つだけであるが、
167 | 現状ではインジケータの色が変更されるだけである。
168 | 以下の例では .suite スタイルに __青(.blue)__ を設定している。
169 |
170 | ```swift
171 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .suite, menuColors: [ .blue ], topBarHeight: statusBarHeight)
172 | ```
173 |
174 | 
175 |
176 |
177 | ### .netlab
178 |
179 | .netlab スタイルで指定できる色は一つだけである。
180 | 現状では、非選択時の文字色に影響する。
181 | 以下の例では .netlab スタイルに __赤(.red)__ を設定している。
182 |
183 | ```swift
184 | pageMenuController = PMKPageMenuController(controllers: controllers, menuStyle: .netlab, menuColors: [ .red ], topBarHeight: statusBarHeight)
185 | ```
186 |
187 | 
188 |
189 |
190 | ## Delegate Methods (optional)
191 |
192 | ページの切り替え時に呼び出される Delegate を使うことも可能。
193 |
194 | ```swift
195 | pageMenuController?.delegate = self
196 | ```
197 |
198 | 上記のような記述を追加して、必要に応じて以下のメソッドを実装してね。
199 | 現時点では、 **.hacka** スタイルのバッジ表示の際に利用しているだけ。
200 |
201 | ```PMKPageMenuControllerDelegte.swift
202 | public protocol PMKPageMenuControllerDelegate: class
203 | {
204 | // ページ画面上でスワイプ操作による切り替えが行われる前に呼び出される
205 | func pageMenuController(_ pageMenuController: PMKPageMenuController, willMoveTo viewController: UIViewController, at menuIndex: Int)
206 | // ページの切り替えが完了した際に呼び出される
207 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didMoveTo viewController: UIViewController, at menuIndex: Int)
208 |
209 | // メニュー項目の作成などが完了した際に呼び出される
210 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didPrepare menuItems: [PMKPageMenuItem])
211 | // メニューがタップされた際に呼び出される
212 | func pageMenuController(_ pageMenuController: PMKPageMenuController, didSelect menuItem: PMKPageMenuItem, at menuIndex: Int)
213 | }
214 | ```
215 |
216 | ## References
217 |
218 | Qiita の[ニュース系アプリのユーザインタフェース PageMenuKit の実装](http://qiita.com/magickworx/items/5de63eb926a9447b2665) も見てね。カスタムメニューの実装方法についても書いてあるよ。
219 |
220 | ## Requirements
221 |
222 | - Swift 5
223 | - iOS 13.6 or later
224 | - Xcode 12.3 or later
225 |
226 | ## ToDo
227 |
228 | - .suite と .web と .netlab スタイルのカスタマイズ方法
229 |
230 | ## License Agreement
231 |
232 | Copyright (c) 2017-2020, Kouichi ABE (WALL) All rights reserved.
233 |
234 | Redistribution and use in source and binary forms, with or without
235 | modification, are permitted provided that the following conditions are met:
236 |
237 | 1. Redistributions of source code must retain the above copyright notice,
238 | this list of conditions and the following disclaimer.
239 |
240 | 2. Redistributions in binary form must reproduce the above copyright notice,
241 | this list of conditions and the following disclaimer in the documentation
242 | and/or other materials provided with the distribution.
243 |
244 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
245 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
247 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
248 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
250 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
251 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
252 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
254 |
255 |
--------------------------------------------------------------------------------
/screenshots/ex_Ellipse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Ellipse.png
--------------------------------------------------------------------------------
/screenshots/ex_Hacka.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Hacka.png
--------------------------------------------------------------------------------
/screenshots/ex_NHK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_NHK.png
--------------------------------------------------------------------------------
/screenshots/ex_NetLab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_NetLab.png
--------------------------------------------------------------------------------
/screenshots/ex_Plain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Plain.png
--------------------------------------------------------------------------------
/screenshots/ex_Smart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Smart.png
--------------------------------------------------------------------------------
/screenshots/ex_Suite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Suite.png
--------------------------------------------------------------------------------
/screenshots/ex_Tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Tab.png
--------------------------------------------------------------------------------
/screenshots/ex_Web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/ex_Web.png
--------------------------------------------------------------------------------
/screenshots/tab_Ellipse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Ellipse.png
--------------------------------------------------------------------------------
/screenshots/tab_Hacka.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Hacka.png
--------------------------------------------------------------------------------
/screenshots/tab_NHK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_NHK.png
--------------------------------------------------------------------------------
/screenshots/tab_NetLab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_NetLab.png
--------------------------------------------------------------------------------
/screenshots/tab_Plain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Plain.png
--------------------------------------------------------------------------------
/screenshots/tab_Smart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Smart.png
--------------------------------------------------------------------------------
/screenshots/tab_Suite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Suite.png
--------------------------------------------------------------------------------
/screenshots/tab_Tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Tab.png
--------------------------------------------------------------------------------
/screenshots/tab_Web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magickworx/PageMenuKitSwift/673e0e69cb0bc8f909ce158799f5a639ee91a978/screenshots/tab_Web.png
--------------------------------------------------------------------------------