Swift 仿QQ的长按手势Menu效果

2017-11-29  本文已影响141人  船长_

本文参考:原Objective-C作者:si1ence

demo.gif

1.满足的条件:

作者:si1ence
链接:http://www.jianshu.com/p/ea2c238c8907

2.实现思路:

3.所用到的知识点:

@objc protocol MenuViewDelegate : NSObjectProtocol {
   @objc optional func menuToThumbup()
   @objc optional func menuToCopy()
   @objc optional func menutoDelete()
   @objc optional func menuToTransmit()
   @objc optional func menuToDowanload()
   @objc optional func menuToPreview()
}

open weak var delegate : MenuViewDelegate?

// MARK: Private Method
extension MenuView {
    
    @objc func thumbupButtonTapped(){
        
        if let delegate = delegate,delegate.responds(to: #selector(delegate.menuToThumbup)) {
            delegate.menuToThumbup!()
        }
        self.removeFromSuperview()
    }
}
struct MenuItemType : OptionSet {
    
    public var rawValue = 0  // 因为RawRepresentable的要求
    public static var copys = MenuItemType(rawValue : 1 << 0)

    public static var transmit = MenuItemType(rawValue : 1 << 1)

    public static var collect = MenuItemType(rawValue : 1 << 2)

    public static var delete = MenuItemType(rawValue : 1 << 3)

    public static var revoke = MenuItemType(rawValue : 1 << 4)

    public static var download = MenuItemType(rawValue : 1 << 5)
}

// 用法示例
if message?.msgDirection == .incoming {
      customMenu.itemType = [.copys,.transmit,.collect,.delete]
}else{
      customMenu.itemType = [.copys,.transmit,.collect,.revoke,.delete]
}
lazy var containerView : UIStackView = {
      let containerView = UIStackView()
      containerView.alignment = .fill
      containerView.isUserInteractionEnabled = true
       return containerView
}()

containerView.addArrangedSubview(copyingButton)
containerView.addArrangedSubview(transmitButton)
containerView.addArrangedSubview(collectButton)
enum ImagePosition {
    case left
    case right
    case top
    case bottom
}

extension UIButton {
    
    /**
     *  利用UIButton的titleEdgeInsets和imageEdgeInsets来实现文字和图片的自由排列
     *  注意:这个方法需要在设置图片和文字之后才可以调用,且button的大小要大于 图片大小+文字大小+spacing
     *
     *  @param spacing 图片和文字的间隔
     */
     func setImagePosition(position : ImagePosition,spacing: CGFloat) {
        
        let imageWith : CGFloat = imageView!.image!.size.width
        let imageHeight : CGFloat = imageView!.image!.size.height
        
        let attrs = [NSAttributedStringKey.font:titleLabel!.font!]
        let labelWidth : CGFloat = titleLabel!.text!.size(withAttributes: attrs).width
        let labelHeight : CGFloat = titleLabel!.text!.size(withAttributes: attrs).height
        
        //image中心移动的x距离
        let imageOffsetX : CGFloat = (imageWith + labelWidth) / 2 - imageWith / 2
        //image中心移动的x距离
        let imageOffsetY : CGFloat = imageHeight / 2 + spacing / 2
        //label中心移动的x距离
        let labelOffsetX : CGFloat = (imageWith + labelWidth / 2) - (imageWith + labelWidth) / 2
        //label中心移动的y距离
        let labelOffsetY : CGFloat = labelHeight / 2 + spacing / 2
        
        switch position {
        case .left:
            imageEdgeInsets = UIEdgeInsetsMake(0, -spacing/2, 0, spacing/2)
            titleEdgeInsets = UIEdgeInsetsMake(0, spacing/2, 0, -spacing/2)
        case .right:
            imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth + spacing/2, 0, -(labelWidth + spacing/2))
            titleEdgeInsets = UIEdgeInsetsMake(0, -(imageHeight + spacing/2), 0, imageHeight + spacing/2)
        case .top:
            imageEdgeInsets = UIEdgeInsetsMake(-imageOffsetY, imageOffsetX, imageOffsetY, -imageOffsetX)
            titleEdgeInsets = UIEdgeInsetsMake(labelOffsetY, -labelOffsetX, -labelOffsetY, labelOffsetX)
        case .bottom:
            imageEdgeInsets = UIEdgeInsetsMake(imageOffsetY, imageOffsetX, -imageOffsetY, -imageOffsetX)
            titleEdgeInsets = UIEdgeInsetsMake(-labelOffsetY, -labelOffsetX, labelOffsetY, labelOffsetX)
         }
    }
}
avatarHeaderView.snp.makeConstraints({ (make) in
    make.top.equalToSuperview()
    make.width.height.equalTo(kAvatarSize)
    make.leading.equalToSuperview().offset(kAvatarMarginH)
})

bubbleView.snp.makeConstraints({ (make) in
    make.width.lessThanOrEqualToSuperview()
    make.left.equalToSuperview().offset(kAvatarSize + 18)
    make.top.equalTo(contentView)
    make.right.lessThanOrEqualTo(contentView).offset(-73)
    make.bottom.equalTo(contentView).offset(-20).priority(.low)
})
enum MessageType : String {
    case text = "text"
    case image = "image"  
    case voice = "voice"
}
var identifier : String {
    get{
        let rawIdentifier = self.msgDirection == .incoming ? kCellIdentifierLeft : kCellIdentifierRight
        return String.init(format: "%@%@", rawIdentifier,self.msgType.rawValue)
    }
}

GitHub下载链接

上一篇 下一篇

猜你喜欢

热点阅读