IOS|IOS 滑动菜单

【IOS|IOS 滑动菜单】完整Demo地址
效果图

IOS|IOS 滑动菜单
文章图片
[滑动菜单效果图-github](https://github.com/AllenOoo/SliderMenu-CollectionView)
结构图
IOS|IOS 滑动菜单
文章图片
结构图.png Item的属性、状态

  • scaleFloat,Item缩放系数。
  • highlightColor,高亮颜色。
  • 原始状态:scaleFloat = 1,颜色设置的初始颜色
  • 正在放大但不是最大:1 < scaleFloat < Max,颜色为透明度为(scaleFloat/Max)的highlightColor
  • 放大至最大:scaleFloat = Max,颜色 = highlightFloat
UIScrollView: 为Items提供更多空间
UIView: 和外部控件联动时控制各Item的状态
代码 Item中,只通过一个scaleFloat属性来控制Item的所有状态这样外部使用不容易乱!
override var scaleFloat: Double { didSet {var scaleColorFloat = scaleFloat; var titleColor:UIColor! if scaleColorFloat < 1.05 { titleColor = UIColor.whiteColor() } else { if scaleColorFloat < 1.20 { scaleColorFloat = 1.2 }titleColor = highlightColor.colorWithAlphaComponent(CGFloat(scaleColorFloat/YZButtonScaleMaxFloat)) } self.setTitleColor(titleColor, forState: .Normal) if isNeededAnimation { if scaleFloat >= YZButtonScaleMaxFloat { UIView.animateWithDuration(YZButtonTransAnimationInterval, animations: { self.transform = self.transScale(YZButtonScaleMaxFloat) }) } else { if scaleFloat <= 1.05 { UIView.animateWithDuration(YZButtonTransAnimationInterval, animations: { self.transform = self.transBack() }) } } } else { if scaleFloat > YZButtonScaleMaxFloat - 0.05 { self.transform = self.transScale(YZButtonScaleMaxFloat) } else { if scaleFloat <= 1.05 { self.transform = self.transBack() } else { self.transform = self.transScale(scaleFloat) } } } isNeededAnimation = false } }

UIView中的方法
  1. 通过手势滑动距离给当前高亮Item和两边的Item做状态设置
func itemScaledByDistance(distance: Double) {/// 给对应的item进行缩放 let scaleFloat = (fabs(distance)/Double(self.frame.width))*YZButtonScaleMaxFloat let currentItem = YZButtons[index] let nextItem : YZButton? if distance > 0 { // 左 if index <= 0 { nextItem = YZButton.init(frame: CGRectZero) } else { nextItem = YZButtons[index-1] } } else { if index >= YZButtons.count-1 { nextItem = YZButton.init(frame: CGRectZero) } else { nextItem = YZButtons[index+1] } } nextItem?.scaleFloat = 1 + scaleFloat currentItem?.scaleFloat = YZButtonScaleMaxFloat - scaleFloat }

2.手势结束设定对应Item设定最终状态
func sliderMenuWillScrollToIndex(targetIndex: NSInteger) { let lastItem : YZButton? let nextItem : YZButton? if targetIndex == 0 { nextItem = YZButtons[targetIndex + 1] lastItem = YZButton.init(frame: CGRectZero) } else if targetIndex >= YZButtons.count - 1 { nextItem = YZButton.init(frame: CGRectZero) lastItem = YZButtons[targetIndex - 1] } else { nextItem = YZButtons[targetIndex + 1] lastItem = YZButtons[targetIndex - 1] } /// 返回初始状态 lastItem?.scaleFloat = YZButtonScaleMinFloat nextItem?.scaleFloat = YZButtonScaleMinFloat index = targetIndex; }

CollectionView中需要传给菜单的数据
1.捕获手势状态
self.panGestureRecognizer.addTarget(self, action: #selector(panGestureActionInState(_:)))func panGestureActionInState(gesture: UIPanGestureRecognizer) { if gesture.state == .Changed { self.gestureDelegate.collectionView(self, panning: gesture) } if gesture.state == .Ended { self.gestureDelegate.collectionView(self, didEndPan: gesture, to: targetIndex) } }

2.将要停止的目标位置
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { let offsetX = targetContentOffset.memory.x targetIndex = lroundf(Float(offsetX/self.frame.width)) }

最后上下联动
/// 在菜单中做点击操作 func didSelectedAtIndex(index: NSInteger, animated: Bool) { collection.scrollToItemAtIndexPath(NSIndexPath.init(forRow: index, inSection: 0), atScrollPosition: .CenteredHorizontally, animated: animated) } /// 滑动CollectionView的过程 func collectionView(collectionView: SliderMenuInfoView, panning pan: UIPanGestureRecognizer) { sliderMenu.itemScaledByDistance(Double(pan.translationInView(collectionView).x)) } /// 手势停止时 func collectionView(collectionView: SliderMenuInfoView, didEndPan pan: UIPanGestureRecognizer, to targetIndex: NSInteger) { sliderMenu.sliderMenuWillScrollToIndex(targetIndex) }

完整Demo地址

    推荐阅读