swift 类微信朋友圈九宫格拖拽图

2020-03-11  本文已影响0人  单抽律化娜
import UIKit

class MomentsViewController: UIViewController {
  
    private var vMoments: MomentsView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        view.backgroundColor = .white
        
        vMoments = MomentsView()
//        vMoments.rowCount = 4
//        vMoments.maxCount = 7
        view.addSubview(vMoments)
        
        vMoments.snp.makeConstraints { (make) in
            make.left.equalTo(20)
            make.top.equalTo(100)
            make.right.equalTo(-20)
            make.height.equalTo(100)
        }
        
        /// 更新高度
        vMoments.heightBlock = { [weak self] height in
            self?.vMoments.snp.updateConstraints { (make) in
                make.height.equalTo(height)
            }
        }
        
        /// 点击按钮
        vMoments.btnPostBlock = { [weak self] in
            self?.uploadImage()
        }
        
        /// 添加长按操作
        let gesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_ :)))
        gesture.minimumPressDuration = 0.5
        view.addGestureRecognizer(gesture)
        
        /// 添加删除区域
        let vDeleteArea = MomentsDeleteView()
        vDeleteArea.isDelete = false
        view.addSubview(vDeleteArea)
        
        vDeleteArea.snp.makeConstraints { (make) in
            make.left.right.bottom.equalToSuperview()
            make.height.equalTo(60)
        }
        
        vDeleteArea.hideView()
        
        vMoments.vDeleteArea = vDeleteArea
    }
    
    /// 添加拖动手势
    @objc private func longPress(_ gesture: UILongPressGestureRecognizer) {
        vMoments.longPress(gesture)
    }
    
    func uploadImage() {
        vMoments.arrData.append(UIImage(named: "fengjingtu\(getRandom(1, 4))")!)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
class MomentsView: UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    /// collectionView
    private lazy var collectionView: UICollectionView = {
        
        let layout = UICollectionViewFlowLayout()
        layout.minimumLineSpacing = itemSpace
        layout.minimumInteritemSpacing = itemSpace
        
        let collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = .clear
        collectionView.register(MomentsViewCell.self, forCellWithReuseIdentifier: "MomentsViewCell")
        addSubview(collectionView)
        
        return collectionView
    }()
    
    /// 上传按钮
    private lazy var btnPost: MomentsPostButton = {
        $0.addTarget(self, action: #selector(btnPostClick(_:)), for: .touchUpInside)
        $0.isHidden = true
        addSubview($0)
        return $0
    }(MomentsPostButton())
    
    /// 长按拖拽元素
    private lazy var dragingItem: UIImageView = {
        $0.contentMode = .scaleAspectFill
        $0.layer.masksToBounds = true
        superview?.insertSubview($0, aboveSubview: self)
        return $0
    }(UIImageView())
    
    /// 拖拽位置
    private var indexPath: IndexPath?
    
    /// 宽高
    private var itemLength: CGFloat = 0 {
        willSet {
            btnPost.snp.updateConstraints { (make) in
                make.size.equalTo(CGSize(width: newValue, height: newValue))
            }
        }
        didSet {
            numberOfLines = 0
        }
    }
    
    /// 行数
    private var numberOfLines: Int = -1 {
        willSet {
            heightBlock?(itemLength + CGFloat(newValue) * (itemLength + itemSpace))
        }
    }
    
    /// 是否能删除
    private var canDelete: Bool = false
    
    /// 最大个数
    var maxCount: Int = 9
    
    /// 一行个数
    var rowCount: Int = 3
    
    /// 间隔
    var itemSpace: CGFloat = 10
    
    /// 高度变化
    var heightBlock: ((CGFloat)->Void)?
    
    /// 按钮回调
    var btnPostBlock: (()->Void)?
    
    /// 删除区域
    weak var vDeleteArea: MomentsDeleteView?
    
    /// 数据
    var arrData: [UIImage] = [] {
        didSet {
            collectionView.reloadData()
        }
    }
    
    /// 初始化
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        btnPost.snp.makeConstraints { (make) in
            make.left.top.equalTo(0)
            make.size.equalTo(CGSize.zero)
        }
        
        collectionView.snp.makeConstraints { (make) in
            make.left.top.right.bottom.equalToSuperview()
        }
    }
    
    /// 上传按钮点击回调
    @objc private func btnPostClick(_ sender: UIButton) {
        btnPostBlock?()
    } 
    
    /// cell个数
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let count = arrData.count
        if (count > 0 && count < maxCount) {
            let lines = count / rowCount
            if (lines != numberOfLines) {
                numberOfLines = lines
            }
        }
        return min(count + 1, maxCount)
    }
    
    /// cell样式
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MomentsViewCell", for: indexPath) as! MomentsViewCell
        cell.imageView.image = indexPath.row < arrData.count ? arrData[indexPath.row] : nil
        return cell
    }
    
    /// cell将要展示
    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if indexPath.row == arrData.count && indexPath.row < maxCount {
            let pos = convert(cell.frame.origin, from: collectionView)
            btnPost.snp.updateConstraints { (make) in
                make.top.equalTo(pos.y)
                make.left.equalTo(pos.x)
            }
        }
        btnPost.isHidden = arrData.count + 1 > maxCount
    }
    
    /// cell宽高
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if (itemLength == 0) {
            itemLength = (collectionView.frame.width - itemSpace * CGFloat(rowCount - 1)) / CGFloat(rowCount)
        }
        return CGSize(width: itemLength, height: itemLength)
    }
    
    /// 长按事件
    public func longPress(_ gesture: UILongPressGestureRecognizer) {
        guard let target = gesture.view, isUserInteractionEnabled else {
            return
        }
        switch gesture.state {
        case .began:
            beginInteractiveMovement(target, position: gesture.location(in: target))
        case .changed:
            updateInteractiveMovement(target, position: gesture.location(in: target))
        case .ended:
            endInteractiveMovement(target)
        case .cancelled:
            endInteractiveMovement(target)
        default:
            break
        }
    }
    
    /// 长按开始
    private func beginInteractiveMovement(_ target: UIView, position: CGPoint) {
        
        guard let indexPath = collectionView.indexPathForItem(at: target.convert(position, to: collectionView)), indexPath.row < arrData.count else {
            return
        }
        
        let cell: MomentsViewCell = collectionView.cellForItem(at: indexPath) as! MomentsViewCell
        cell.isHidden = true
        
        dragingItem.frame = CGRect(origin: collectionView.convert(cell.frame.origin, to: target), size: cell.frame.size)
        dragingItem.image = cell.imageView.image
        dragingItem.isHidden = false
        
        UIView.animate(withDuration: 0.1, animations: {
            self.dragingItem.center = position
            self.dragingItem.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
            self.vDeleteArea?.showView()
        }) { (finished) in
            self.indexPath = indexPath
        }
    }
    
    /// 长按过程
    private func updateInteractiveMovement(_ target: UIView, position: CGPoint) {
        
        guard let indexPath = indexPath else {
            return
        }
        
        dragingItem.center = position
        
        if let vDeleteArea = vDeleteArea {
            if vDeleteArea.frame.contains(position) {
                canDelete = true
                vDeleteArea.isDelete = true
            } else {
                canDelete = false
                vDeleteArea.isDelete = false
            }
        }
        
        guard let targetIndexPath = collectionView.indexPathForItem(at: target.convert(position, to: collectionView)), targetIndexPath.row < arrData.count else {
            return
        }
        
        /// 交换位置
        collectionView.moveItem(at: indexPath, to: targetIndexPath)
        
        let obj = arrData[indexPath.row]
        arrData.remove(at: indexPath.row)
        arrData.insert(obj, at: targetIndexPath.row)
        
        self.indexPath = targetIndexPath
    }
    
    /// 长按结束
    private func endInteractiveMovement(_ target: UIView) {
        
        guard let indexPath = indexPath, let cell = collectionView.cellForItem(at: indexPath) else {
            return
        }
        
        isUserInteractionEnabled = false
        
        if (canDelete) {
            UIView.animate(withDuration: 0.1, animations: {
                self.vDeleteArea?.hideView()
            }, completion: { (finished) in
                self.arrData.remove(at: indexPath.row)
                self.collectionView.reloadData()
                cell.isHidden = false
                self.dragingItem.isHidden = true
                self.indexPath = nil
                self.vDeleteArea?.isDelete = false
                self.isUserInteractionEnabled = true
            })
        } else {
            let center = target.convert(cell.center, from: collectionView)
            UIView.animate(withDuration: 0.25, animations: {
                self.dragingItem.transform = .identity
                self.dragingItem.center = center
                self.vDeleteArea?.hideView()
            }, completion: { (finished) in
                cell.isHidden = false
                self.dragingItem.isHidden = true
                self.indexPath = nil
                self.vDeleteArea?.isDelete = false
                self.isUserInteractionEnabled = true
            })
        }
    }
    
    /// 判断是不是按钮点击
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if !btnPost.isHidden && (collectionView.convert(btnPost.frame, from: self).contains(point)) {
            return btnPost
        }
        return super.hitTest(point, with: event)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
class MomentsViewCell: UICollectionViewCell {
    
    var imageView: UIImageView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.layer.masksToBounds = true
        addSubview(imageView)
        
        imageView.snp.makeConstraints { (make) in
            make.left.right.top.bottom.equalToSuperview()
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
/// 上传按钮
class MomentsPostButton: UIButton {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        let borderWidth: CGFloat = 2
        let borderColor: UIColor = .gray
        
        backgroundColor = UIColor.groupTableViewBackground
        
        /// 横
        let vHorizontal = UIView()
        vHorizontal.backgroundColor = borderColor
        addSubview(vHorizontal)
        
        vHorizontal.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
            make.width.equalToSuperview().multipliedBy(0.25)
            make.height.equalTo(borderWidth)
        }
        
        /// 竖
        let vVertical = UIView()
        vVertical.backgroundColor = borderColor
        addSubview(vVertical)
        
        vVertical.snp.makeConstraints { (make) in
            make.width.equalTo(borderWidth)
            make.center.equalToSuperview()
            make.height.equalToSuperview().multipliedBy(0.25)
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
class MomentsDeleteView: UILabel {
    
    let normalText = "拖到此处删除"
    
    let normalColor = UIColor(hex: "ff0033").withAlphaComponent(0.9)
    
    let deleteText = "松手即可删除"
    
    let deleteColor = UIColor(hex: "cc0000").withAlphaComponent(0.9)
    
    var isDelete: Bool = false {
        didSet {
            if isDelete {
                text = deleteText
                backgroundColor = deleteColor
            } else {
                text = normalText
                backgroundColor = normalColor
            }
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = normalColor
        text = normalText
        textColor = .white
        font = UIFont.systemFont(ofSize: 14)
        textAlignment = .center
    }
    
    func showView() {
        transform = .identity
    }
    
    func hideView() {
        transform = CGAffineTransform(translationX: 0, y: 60)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
上一篇下一篇

猜你喜欢

热点阅读