0
This is my actual view更改sidemenu
我想的是,sidemenu始於第一灰線,而不是在圖的頂部的高度。如果我能得到答案,我會很高興,我可以如何設定它的高度,但如果有人可以建議我將搜索欄隱藏在搜索欄和分段控制之後,我也很高興。先謝謝你。
這是我ENSideMenu.swift實施
import UIKit
@objc public protocol ENSideMenuDelegate {
optional func sideMenuWillOpen()
optional func sideMenuWillClose()
optional func sideMenuDidOpen()
optional func sideMenuDidClose()
optional func sideMenuShouldOpenSideMenu() -> Bool
}
@objc public protocol ENSideMenuProtocol {
var sideMenu : ENSideMenu? { get }
func setContentViewController(contentViewController: UIViewController)
}
public enum ENSideMenuAnimation : Int {
case None
case Default
}
/**
The position of the side view on the screen.
- Left: Left side of the screen
- Right: Right side of the screen
*/
public enum ENSideMenuPosition : Int {
case Left
case Right
}
public extension UIViewController {
/**
Changes current state of side menu view.
*/
public func toggleSideMenuView() {
sideMenuController()?.sideMenu?.toggleMenu()
}
/**
Hides the side menu view.
*/
public func hideSideMenuView() {
sideMenuController()?.sideMenu?.hideSideMenu()
}
/**
Shows the side menu view.
*/
public func showSideMenuView() {
sideMenuController()?.sideMenu?.showSideMenu()
}
/**
Returns a Boolean value indicating whether the side menu is showed.
:returns: BOOL value
*/
public func isSideMenuOpen() -> Bool {
let sieMenuOpen = self.sideMenuController()?.sideMenu?.isMenuOpen
return sieMenuOpen!
}
/**
* You must call this method from viewDidLayoutSubviews in your content view controlers so it fixes size and position of the side menu when the screen
* rotates.
* A convenient way to do it might be creating a subclass of UIViewController that does precisely that and then subclassing your view controllers from it.
*/
func fixSideMenuSize() {
if let navController = self.navigationController as? ENSideMenuNavigationController {
navController.sideMenu?.updateFrame()
}
}
/**
Returns a view controller containing a side menu
:returns: A `UIViewController`responding to `ENSideMenuProtocol` protocol
*/
public func sideMenuController() -> ENSideMenuProtocol? {
var iteration : UIViewController? = self.parentViewController
if (iteration == nil) {
return topMostController()
}
repeat {
if (iteration is ENSideMenuProtocol) {
return iteration as? ENSideMenuProtocol
} else if (iteration?.parentViewController != nil && iteration?.parentViewController != iteration) {
iteration = iteration!.parentViewController
} else {
iteration = nil
}
} while (iteration != nil)
return iteration as? ENSideMenuProtocol
}
internal func topMostController() -> ENSideMenuProtocol? {
var topController : UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController
if (topController is UITabBarController) {
topController = (topController as! UITabBarController).selectedViewController
}
while (topController?.presentedViewController is ENSideMenuProtocol) {
topController = topController?.presentedViewController
}
return topController as? ENSideMenuProtocol
}
}
public class ENSideMenu : NSObject, UIGestureRecognizerDelegate {
/// The width of the side menu view. The default value is 160.
public var menuWidth : CGFloat = 90.0 {
didSet {
needUpdateApperance = true
updateFrame()
}
}
private var menuPosition:ENSideMenuPosition = .Right
private var blurStyle: UIBlurEffectStyle = .Light
/// A Boolean value indicating whether the bouncing effect is enabled. The default value is TRUE.
public var bouncingEnabled :Bool = true
/// The duration of the slide animation. Used only when `bouncingEnabled` is FALSE.
public var animationDuration = 0.25
private let sideMenuContainerView = UIView()
private(set) var menuViewController : UIViewController!
private var animator : UIDynamicAnimator!
private var sourceView : UIView!
private var needUpdateApperance : Bool = false
/// The delegate of the side menu
public weak var delegate : ENSideMenuDelegate?
private(set) var isMenuOpen : Bool = false
/// A Boolean value indicating whether the left swipe is enabled.
public var allowLeftSwipe : Bool = true
/// A Boolean value indicating whether the right swipe is enabled.
public var allowRightSwipe : Bool = true
public var allowPanGesture : Bool = true
private var panRecognizer : UIPanGestureRecognizer?
/**
Initializes an instance of a `ENSideMenu` object.
:param: sourceView The parent view of the side menu view.
:param: menuPosition The position of the side menu view.
:returns: An initialized `ENSideMenu` object, added to the specified view.
*/
public init(sourceView: UIView, menuPosition: ENSideMenuPosition, blurStyle: UIBlurEffectStyle = .Light) {
super.init()
self.sourceView = sourceView
self.menuPosition = menuPosition
self.blurStyle = blurStyle
self.setupMenuView()
animator = UIDynamicAnimator(referenceView:sourceView)
animator.delegate = self
self.panRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
panRecognizer!.delegate = self
sourceView.addGestureRecognizer(panRecognizer!)
// Add right swipe gesture recognizer
let rightSwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleGesture:")
rightSwipeGestureRecognizer.delegate = self
rightSwipeGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Right
// Add left swipe gesture recognizer
let leftSwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleGesture:")
leftSwipeGestureRecognizer.delegate = self
leftSwipeGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Left
if (menuPosition == .Left) {
sourceView.addGestureRecognizer(rightSwipeGestureRecognizer)
sideMenuContainerView.addGestureRecognizer(leftSwipeGestureRecognizer)
}
else {
sideMenuContainerView.addGestureRecognizer(rightSwipeGestureRecognizer)
sourceView.addGestureRecognizer(leftSwipeGestureRecognizer)
}
}
/**
Initializes an instance of a `ENSideMenu` object.
:param: sourceView The parent view of the side menu view.
:param: menuViewController A menu view controller object which will be placed in the side menu view.
:param: menuPosition The position of the side menu view.
:returns: An initialized `ENSideMenu` object, added to the specified view, containing the specified menu view controller.
*/
public convenience init(sourceView: UIView, menuViewController: UIViewController, menuPosition: ENSideMenuPosition, blurStyle: UIBlurEffectStyle = .Light) {
self.init(sourceView: sourceView, menuPosition: menuPosition, blurStyle: blurStyle)
self.menuViewController = menuViewController
self.menuViewController.view.frame = sideMenuContainerView.bounds
self.menuViewController.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
sideMenuContainerView.addSubview(self.menuViewController.view)
}
/*
public convenience init(sourceView: UIView, view: UIView, menuPosition: ENSideMenuPosition) {
self.init(sourceView: sourceView, menuPosition: menuPosition)
view.frame = sideMenuContainerView.bounds
view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
sideMenuContainerView.addSubview(view)
}
*/
/**
Updates the frame of the side menu view.
*/
func updateFrame() {
var width:CGFloat
var height:CGFloat
(width, height) = adjustFrameDimensions(sourceView.frame.size.width, height: sourceView.frame.size.height)
let menuFrame = CGRectMake(
(menuPosition == .Left) ?
isMenuOpen ? 0 : -menuWidth-1.0 :
isMenuOpen ? width - menuWidth : width+1.0,
sourceView.frame.origin.y,
menuWidth,
height
)
sideMenuContainerView.frame = menuFrame
}
private func adjustFrameDimensions(width: CGFloat, height: CGFloat) -> (CGFloat,CGFloat) {
if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 &&
(UIApplication.sharedApplication().statusBarOrientation == UIInterfaceOrientation.LandscapeRight ||
UIApplication.sharedApplication().statusBarOrientation == UIInterfaceOrientation.LandscapeLeft) {
// iOS 7.1 or lower and landscape mode -> interchange width and height
return (height, width)
}
else {
return (width, height)
}
}
private func setupMenuView() {
// Configure side menu container
updateFrame()
sideMenuContainerView.backgroundColor = UIColor.clearColor()
sideMenuContainerView.clipsToBounds = false
sideMenuContainerView.layer.masksToBounds = false
sideMenuContainerView.layer.shadowOffset = (menuPosition == .Left) ? CGSizeMake(1.0, 1.0) : CGSizeMake(-1.0, -1.0)
sideMenuContainerView.layer.shadowRadius = 1.25
sideMenuContainerView.layer.shadowOpacity = 0.125
sideMenuContainerView.layer.shadowPath = UIBezierPath(rect: sideMenuContainerView.bounds).CGPath
sourceView.addSubview(sideMenuContainerView)
if (NSClassFromString("UIVisualEffectView") != nil) {
// Add blur view
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: blurStyle)) as UIVisualEffectView
visualEffectView.frame = sideMenuContainerView.bounds
visualEffectView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
sideMenuContainerView.addSubview(visualEffectView)
}
else {
// TODO: add blur for ios 7
}
}
private func toggleMenu (shouldOpen: Bool) {
if (shouldOpen && delegate?.sideMenuShouldOpenSideMenu?() == false) {
return
}
updateSideMenuApperanceIfNeeded()
isMenuOpen = shouldOpen
var width:CGFloat
var height:CGFloat
(width, height) = adjustFrameDimensions(sourceView.frame.size.width, height: sourceView.frame.size.height)
if (bouncingEnabled) {
animator.removeAllBehaviors()
var gravityDirectionX: CGFloat
var pushMagnitude: CGFloat
var boundaryPointX: CGFloat
var boundaryPointY: CGFloat
if (menuPosition == .Left) {
// Left side menu
gravityDirectionX = (shouldOpen) ? 1 : -1
pushMagnitude = (shouldOpen) ? 20 : -20
boundaryPointX = (shouldOpen) ? menuWidth : -menuWidth-2
boundaryPointY = 20
}
else {
// Right side menu
gravityDirectionX = (shouldOpen) ? -1 : 1
pushMagnitude = (shouldOpen) ? -20 : 20
boundaryPointX = (shouldOpen) ? width-menuWidth : width+menuWidth+2
boundaryPointY = -20
}
let gravityBehavior = UIGravityBehavior(items: [sideMenuContainerView])
gravityBehavior.gravityDirection = CGVectorMake(gravityDirectionX, 0)
animator.addBehavior(gravityBehavior)
let collisionBehavior = UICollisionBehavior(items: [sideMenuContainerView])
collisionBehavior.addBoundaryWithIdentifier("menuBoundary", fromPoint: CGPointMake(boundaryPointX, boundaryPointY),
toPoint: CGPointMake(boundaryPointX, height))
animator.addBehavior(collisionBehavior)
let pushBehavior = UIPushBehavior(items: [sideMenuContainerView], mode: UIPushBehaviorMode.Instantaneous)
pushBehavior.magnitude = pushMagnitude
animator.addBehavior(pushBehavior)
let menuViewBehavior = UIDynamicItemBehavior(items: [sideMenuContainerView])
menuViewBehavior.elasticity = 0.25
animator.addBehavior(menuViewBehavior)
}
else {
var destFrame :CGRect
if (menuPosition == .Left) {
destFrame = CGRectMake((shouldOpen) ? -2.0 : -menuWidth, 0, menuWidth, height)
}
else {
destFrame = CGRectMake((shouldOpen) ? width-menuWidth : width+2.0,
0,
menuWidth,
height)
}
UIView.animateWithDuration(
animationDuration,
animations: {() -> Void in
self.sideMenuContainerView.frame = destFrame
},
completion: { (Bool) -> Void in
if (self.isMenuOpen) {
self.delegate?.sideMenuDidOpen?()
} else {
self.delegate?.sideMenuDidClose?()
}
})
}
if (shouldOpen) {
delegate?.sideMenuWillOpen?()
} else {
delegate?.sideMenuWillClose?()
}
/*let outterView = UIView(frame: CGRectMake(sideMenuContainerView.frame.width, 0,
sourceView.frame.width - sideMenuContainerView.frame.width,
sourceView.frame.height))
outterView.backgroundColor = UIColor.clearColor()
let tapRecognizer = UITapGestureRecognizer(target: self, action: "hideSideMenu")
outterView.addGestureRecognizer(tapRecognizer)
outterView.userInteractionEnabled = false
sourceView.addSubview(outterView)
sourceView.layer.zPosition = 0
outterView.userInteractionEnabled = shouldOpen */
}
public func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UISwipeGestureRecognizer {
let swipeGestureRecognizer = gestureRecognizer as! UISwipeGestureRecognizer
if !self.allowLeftSwipe {
if swipeGestureRecognizer.direction == .Left {
return false
}
}
if !self.allowRightSwipe {
if swipeGestureRecognizer.direction == .Right {
return false
}
}
}
else if gestureRecognizer.isEqual(panRecognizer) {
if allowPanGesture == false {
return false
}
animator.removeAllBehaviors()
let touchPosition = gestureRecognizer.locationOfTouch(0, inView: sourceView)
if menuPosition == .Left {
if isMenuOpen {
if touchPosition.x < menuWidth {
return true
}
}
else {
if touchPosition.x < 25 {
return true
}
}
}
else {
if isMenuOpen {
if touchPosition.x > CGRectGetWidth(sourceView.frame) - menuWidth {
return true
}
}
else {
if touchPosition.x > CGRectGetWidth(sourceView.frame)-25 {
return true
}
}
}
return false
}
return true
}
internal func handleGesture(gesture: UISwipeGestureRecognizer) {
toggleMenu((self.menuPosition == .Right && gesture.direction == .Left)
|| (self.menuPosition == .Left && gesture.direction == .Right))
}
internal func handlePan(recognizer : UIPanGestureRecognizer){
let leftToRight = recognizer.velocityInView(recognizer.view).x > 0
switch recognizer.state {
case .Began:
break
case .Changed:
let translation = recognizer.translationInView(sourceView).x
let xPoint : CGFloat = sideMenuContainerView.center.x + translation + (menuPosition == .Left ? 1 : -1) * menuWidth/2
if menuPosition == .Left {
if xPoint <= 0 || xPoint > CGRectGetWidth(self.sideMenuContainerView.frame) {
return
}
}else{
if xPoint <= sourceView.frame.size.width - menuWidth || xPoint >= sourceView.frame.size.width
{
return
}
}
sideMenuContainerView.center.x = sideMenuContainerView.center.x + translation
recognizer.setTranslation(CGPointZero, inView: sourceView)
default:
let shouldClose = menuPosition == .Left ? !leftToRight && CGRectGetMaxX(sideMenuContainerView.frame) < menuWidth : leftToRight && CGRectGetMinX(sideMenuContainerView.frame) > (sourceView.frame.size.width - menuWidth)
toggleMenu(!shouldClose)
}
}
private func updateSideMenuApperanceIfNeeded() {
if (needUpdateApperance) {
var frame = sideMenuContainerView.frame
frame.size.width = menuWidth
sideMenuContainerView.frame = frame
sideMenuContainerView.layer.shadowPath = UIBezierPath(rect: sideMenuContainerView.bounds).CGPath
needUpdateApperance = false
}
}
/**
Toggles the state of the side menu.
*/
public func toggleMenu() {
if (isMenuOpen) {
toggleMenu(false)
}
else {
updateSideMenuApperanceIfNeeded()
toggleMenu(true)
}
}
/**
Shows the side menu if the menu is hidden.
*/
public func showSideMenu() {
if (!isMenuOpen) {
toggleMenu(true)
}
}
/**
Hides the side menu if the menu is showed.
*/
public func hideSideMenu() {
if (isMenuOpen) {
toggleMenu(false)
}
}
}
extension ENSideMenu: UIDynamicAnimatorDelegate {
public func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
if (self.isMenuOpen) {
self.delegate?.sideMenuDidOpen?()
} else {
self.delegate?.sideMenuDidClose?()
}
}
public func dynamicAnimatorWillResume(animator: UIDynamicAnimator) {
print("resume")
}
}
這是我ENSideMenuNavigationController.swift
import UIKit
public class ENSideMenuNavigationController: UINavigationController, ENSideMenuProtocol {
public var sideMenu : ENSideMenu?
public var sideMenuAnimationType : ENSideMenuAnimation = .Default
// MARK: - Life cycle
public override func viewDidLoad() {
super.viewDidLoad()
}
public init(menuViewController: UIViewController, contentViewController: UIViewController?) {
super.init(nibName: nil, bundle: nil)
if (contentViewController != nil) {
self.viewControllers = [contentViewController!]
}
sideMenu = ENSideMenu(sourceView: self.view, menuViewController: menuViewController, menuPosition:.Right)
view.bringSubviewToFront(navigationBar)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
public func setContentViewController(contentViewController: UIViewController) {
self.sideMenu?.toggleMenu()
switch sideMenuAnimationType {
case .None:
self.viewControllers = [contentViewController]
break
default:
contentViewController.navigationItem.hidesBackButton = true
self.setViewControllers([contentViewController], animated: true)
break
}
}
}
這是我MyMenuTableViewController:
import UIKit
class MyMenuTableViewController: UITableViewController {
var selectedMenuItem : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Customize apperance of table view
tableView.contentInset = UIEdgeInsetsMake(116.0, 0, 0, 0) //
tableView.separatorStyle = .None
tableView.backgroundColor = UIColor.whiteColor()
tableView.scrollsToTop = false
tableView.allowsSelection = false
// Preserve selection between presentations
self.clearsSelectionOnViewWillAppear = false
tableView.selectRowAtIndexPath(NSIndexPath(forRow: selectedMenuItem, inSection: 0), animated: false, scrollPosition: .Middle)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CELL")
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CELL")
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel?.textColor = UIColor.darkGrayColor()
let selectedBackgroundView = UIView(frame: CGRectMake(0, 0, cell!.frame.size.width, cell!.frame.size.height))
selectedBackgroundView.backgroundColor = UIColor.grayColor().colorWithAlphaComponent(0.2)
cell!.selectedBackgroundView = selectedBackgroundView
}
//cell!.textLabel?.text = "social Network #\(indexPath.row+1)"
cell!.imageView?.image = UIImage(named: "Facebook")
return cell!
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 45.0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("did select row: \(indexPath.row)")
if (indexPath.row == selectedMenuItem) {
return
}
selectedMenuItem = indexPath.row
//Present new view controller
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main",bundle: nil)
var destViewController : UIViewController
switch (indexPath.row) {
case 0:
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController1")
break
case 1:
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController2")
break
case 2:
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController3")
break
default:
destViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController4")
break
}
sideMenuController()?.setContentViewController(destViewController)
}
}
這是我MyNavigationController.swift
import UIKit
class MyNavigationController: ENSideMenuNavigationController, ENSideMenuDelegate {
override func viewDidLoad() {
super.viewDidLoad()
sideMenu = ENSideMenu(sourceView: self.view, menuViewController: MyMenuTableViewController(), menuPosition:.Right)
//sideMenu?.delegate = self //optional
sideMenu?.menuWidth = 90.0 // optional, default is 160
// sideMenu?.bouncingEnabled = false
//sideMenu?.allowPanGesture = false
// make navigation bar showing over side menu
view.bringSubviewToFront(navigationBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - ENSideMenu Delegate
func sideMenuWillOpen() {
print("sideMenuWillOpen")
}
func sideMenuWillClose() {
print("sideMenuWillClose")
}
func sideMenuDidClose() {
print("sideMenuDidClose")
}
func sideMenuDidOpen() {
print("sideMenuDidOpen")
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Downvote:請添加代碼,你可以使用你的框架側邊欄等 – AncAinu
我已經編輯我的職務。對不起 – devtimg
沒問題,我刪除了我的downvote;) – AncAinu