美文网首页
仿写ofo之下拉菜单效果

仿写ofo之下拉菜单效果

作者: 程序H | 来源:发表于2017-10-25 16:37 被阅读65次

    在项目不忙之余,心血来潮突然想仿写一个ofo,本人会把项目中写的控件及技术点罗列出来,与同僚共同学习的同时,也是对自己学习的总结。

    本章节仅实现ofo底部扫码视图弹出效果。


    效果图

    贝塞尔曲线画圆角

    首先底部视图上的弧度是通过Quart2D实现,首先在View引出drawRect方法。
    drawRect方法提供UIView的重绘机制,可以在此方法中进行绘图,因此类教程颇多具体就不细说了。
    上代码:

    override func draw(_ rect: CGRect) {
        let ctx = UIGraphicsGetCurrentContext()
        // 此为移动到的位置
        ctx?.move(to: CGPoint(x: SCREEN_W, y: 50))
        // 添加贝塞尔曲线 control 参数表弧线坐标点
        ctx?.addQuadCurve(to: CGPoint(x: 0, y: 50), control: CGPoint(x: SCREEN_W/2, y: -33))
        // 从左下角至移动点画一条线
        ctx?.addLine(to: CGPoint(x: 0, y: self.height))
        // 从右下角至移动点画一条线
        ctx?.addLine(to: CGPoint(x: SCREEN_W, y: self.height))
        // 填充背景为白色
        ctx?.setFillColor(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1))
        // 设置线条阴影
        ctx?.setShadow(offset: CGSize(width: 0, height: 0), blur: 0.8, color: #colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1))
        // 此处fill表示仅填充
        ctx?.drawPath(using: .fill)
    }
    

    拖动手势

    此处功能很简单,在底部UIView上创建上划及下滑手势,因打开APP默认底部视图是展开所以此处设置topRecognizer.isEnabled默认为false

    // MARK: - 上划手势
    lazy var topRecognizer: UISwipeGestureRecognizer = {
        let topRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeFrom(recognizer:)))
        topRecognizer.isEnabled = false
        topRecognizer.direction = .up
        return topRecognizer
    }()
    
    // MARK: - 下划手势
    lazy var downRecognizer: UISwipeGestureRecognizer = {
        let downRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeFrom(recognizer:)))
        downRecognizer.direction = .down
        return downRecognizer
    }()
    

    通过判断滑动手势来处理上划还是下划,并且与点击or方法公用

    // MARK: - 手势滑动方法
    @objc func handleSwipeFrom(recognizer: UISwipeGestureRecognizer) {
        if recognizer.direction == .up {
            changeArrow()
        } else if recognizer.direction == .down {
            changeArrow()
        }
    }
    
    // MARK: - 视图打开or回收
    private func changeArrow() {
        if isHiddenBottomView == false {
            arrowButton.setImage(#imageLiteral(resourceName: "arrowup"), for: .normal)
        } else {
            arrowButton.setImage(#imageLiteral(resourceName: "arrowdown"), for: .normal)
        }
        topRecognizer.isEnabled = !isHiddenBottomView
        downRecognizer.isEnabled = isHiddenBottomView
        isHiddenBottomView = !isHiddenBottomView
        delegate?.didSelectedArrowButton(isHiddenBottomView: isHiddenBottomView)
    }
    

    didSelectedArrowButton代理方法为返回到背景时控制View约束的回调

    // didSelectedArrowButton代理方法,控制点击`∧`or`∨` and 上划下滑
    func didSelectedArrowButton(isHiddenBottomView: Bool) {
        updateBottomViewWithExpand(isExpanded: isHiddenBottomView, animated: true)
    }
    
    // 此方法控制底部视图约束
    private func updateBottomViewWithExpand(isExpanded:Bool = false, animated:Bool = false, duration:TimeInterval = 0.25) {
        bottomView.snp.updateConstraints { (make) in
            make.left.right.equalTo(self)
            make.height.equalTo(280)
            if isExpanded == true {
                make.bottom.equalTo(snp.bottom).offset(210)
            } else {
                make.bottom.equalTo(snp.bottom)
            }
        }
        
        if animated == true {
            self.needsUpdateConstraints()
            self.updateConstraintsIfNeeded()
            
            UIView.animate(withDuration: duration, animations: {
                self.layoutIfNeeded()
            }, completion: { (completion) in
                self.bottomView.updateWithExpand(isExpanded: isExpanded, animated: true, duration: 0.2)
            })
        }
    }
    

    视图上划后扫码等按钮上移动画

    updateBottomViewWithExpand方法中,在动画结束后引出bottomView(底部视图)updateWithExpand来更新bottomView(底部视图)的约束,从而实现扫码等按钮跟随底部视图上移而上移的动画效果。

    open func updateWithExpand(isExpanded:Bool = false, animated:Bool = false, duration:TimeInterval = 0.25) {
        startButton.snp.updateConstraints { (make) in
            make.centerX.equalTo(self)
            make.width.equalTo(snp.width).multipliedBy(0.55)
            make.height.equalTo(startButton.snp.width)
            if isExpanded {
                make.top.equalTo(arrowButton.snp.bottom).offset(30)
            } else {
                make.top.equalTo(arrowButton.snp.bottom).offset(15)
            }
        }
        
        loginButton.snp.updateConstraints { (make) in
            make.left.equalTo(snp.left).offset(20)
            make.width.equalTo(30)
            make.height.equalTo(loginButton.snp.width)
            
            if isExpanded {
                make.bottom.equalTo(snp.bottom).offset(30)
            } else {
                make.bottom.equalTo(snp.bottom).offset(-15)
            }
        }
        
        newsButton.snp.updateConstraints { (make) in
            make.right.equalTo(snp.right).offset(-20)
            make.width.equalTo(30)
            make.height.equalTo(newsButton.snp.width)
            
            if isExpanded {
                make.bottom.equalTo(snp.bottom).offset(15)
            } else {
                make.bottom.equalTo(snp.bottom).offset(-15)
            }
        }
        
        if animated == true {
            self.needsUpdateConstraints()
            self.updateConstraintsIfNeeded()
            UIView.animate(withDuration: duration, animations: {
                self.layoutIfNeeded()
            })
        }
    }
    

    完整代码后续会进行上传~

    相关文章

      网友评论

          本文标题:仿写ofo之下拉菜单效果

          本文链接:https://www.haomeiwen.com/subject/ozvqpxtx.html