swift 自定义购物车计数器

前端之家收集整理的这篇文章主要介绍了swift 自定义购物车计数器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

<span style="font-family: SimSun; background-color: rgb(255,255,255);">看着公司项目中拥有这个自定义控件,想想后面肯定也要替换成swift的,所以,就开始动手干了起来.</span>

购物车计数器,目前设计了两种类型,一种就是线框圆角,一种就是按钮圆形.

目前支持加/减,以及设置每一步增加或减少的数值,支持闭包回调.当然同时也涉及了简单的VFL(Visual Format Language)的使用.

就目前来说,离笔者想要的功能也大致一样了,如果有新的功能,大家可以修改修改.

效果图是这样的,就没有制作动图了,将就吧:


那先上代码了:

//
//  NBCountView.swift
//  NBCountView
//
//  Created by NapoleonBai on 15/9/20.
//  Copyright © 2015年 NapoleonBai. All rights reserved.
//

import UIKit

enum NBCountViewShowType{
    /// 圆角按钮
    case FilletButton
    /// 圆形按钮
    case CircleButton
}

struct NBCountConfig {
    /// 设置私有属性显示样式
    private var mCountViewType : NBCountViewShowType = .FilletButton
    var countViewShowType : NBCountViewShowType{
        get{
            return mCountViewType
        }
        set(newShowType){
            self.mCountViewType = newShowType
        }
    }
    
    /// 设置私有属性TintColor
    private var mTintColor : UIColor = UIColor.greenColor()
    var tintColor : UIColor {
        get{
            return mTintColor
        }
        set(newTintColor){
            self.mTintColor = newTintColor
        }
    }
    init(){}
    /**
    增加带参数的构造方法
    
    - parameter countViewShowType: 显示样式
    - parameter borderColor:       borderColor
    
    - returns: 当前结构体实例
    */
    init(countViewShowType:NBCountViewShowType,tintColor:UIColor){
        self.countViewShowType = countViewShowType
        self.tintColor = tintColor
    }
}

class NBCountView : UIView,UITextFieldDelegate{

    
    /// 设置默认的两个按钮以及输入框
    private var lessBtn : UIButton = UIButton.init(type:.Custom)
    private var addBtn : UIButton = UIButton.init(type:.Custom)
    private var countTextField : UITextField = UITextField.init()
    
    private var mViewConfig : NBCountConfig = NBCountConfig()
    /// 修改之前的值
    private var updateAgainValue = 0
    /// 当前显示值,缺省为0
    private var mCurrentValue : Int = 0
    /// 当前显示值,动态设置
    var currentValue : Int{
        get{
            return mCurrentValue
        }
        set(newCurrentValue){
            self.mCurrentValue = newCurrentValue
            self.updateAgainValue = self.mCurrentValue
            self.countTextField.text = "\(self.mCurrentValue)"
        }
    }
    
    /// 每次增加或改变多少,缺省为1
    var stepValue : Int = 1
    /// 是否可以手动编辑数值
    var isEditTextField : Bool = false
    
    var viewConfig : NBCountConfig{
        set(newConfig){
            self.mViewConfig = newConfig
            //更新相关配置属性
            updateConfig()
        }
        get{
            return self.mViewConfig
        }
    }

    /// 当前数值改变回调(得到当前显示数量)
    var notifyUpdateCurrentValue : ((currentValue : Int) ->Void)!
    /// 当前数值改变时回调(得到的是每次更改的数量)
    var notifyUpdateStepValue : ((updateStepValue : Int) -> Void)!
    /**
    无参构造函数
    */
    convenience init(){
        //默认调用init frame
        self.init(frame: CGRectZero)
    }
    
    /**
    重新构造方法,创建View
    
    - parameter frame: 指定frame
    */
    override init(frame: CGRect) {
        super.init(frame: frame)
        buildUI()
    }
    
    /**
    从视图控制器中拖此控件,从这里加载
    */
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        buildUI()
    }

    /**
    创建UI
    */
    func buildUI(){
        lessBtn = UIButton.init(type: UIButtonType.Custom)
        addBtn = UIButton.init(type: .Custom)
        countTextField = UITextField.init()
        
        lessBtn.setTitle("-",forState: .Normal)
        addBtn.setTitle("+",forState: .Normal)
        countTextField.text = "\(mCurrentValue)"
        updateAgainValue = mCurrentValue
        
        lessBtn.titleLabel?.font = UIFont.boldSystemFontOfSize(30)
        addBtn.titleLabel?.font = UIFont.boldSystemFontOfSize(30)
        countTextField.textAlignment = .Center
        countTextField.keyboardType = .NumberPad
        countTextField.delegate = self
        countTextField .addTarget(self,action:"textFieldValueChange:",forControlEvents: .EditingChanged)
        
        self.addSubview(lessBtn)
        self.addSubview(addBtn)
        self.addSubview(countTextField)
        
        lessBtn.addTarget(self,action:"onClickLessBtn:",forControlEvents:.TouchUpInside)
        addBtn.addTarget(self,action:"onClickAddBtn:",forControlEvents:.TouchUpInside)

        //self.updateConfig()
        addAutoLayoutContas()
    }
    
    func onClickLessBtn(lessBtn : UIButton){
        self.updateDisplayCurrentValue(-stepValue)
    }
    
    func onClickAddBtn(addBtn : UIButton){
        self.updateDisplayCurrentValue(stepValue)
    }
    
    func updateDisplayCurrentValue(updateStepCount : Int){
        countTextField.resignFirstResponder()
        //获取当前数值
        let currentValueInt = (countTextField.text! as NSString).integerValue
        //改变当前数值
        mCurrentValue = currentValueInt + updateStepCount
        //重新设置当前数值
        countTextField.text = "\(mCurrentValue)"
        /**
        回调,传入当前显示值
        - parameter currentValue: 当前显示数值
        */
        notifyUpdateCurrentValue?(currentValue:mCurrentValue)
        /**
        回调,传入当前更改的数量
        
        - parameter updateStepValue: 当前更改的数量
        */
        notifyUpdateStepValue?(updateStepValue:updateStepCount)
        self.updateAgainValue = self.mCurrentValue
    }

    
    /**
    设置相关属性
    */
    func updateConfig(){
        //如果这是第一种类型,也就是圆角按钮,设置边框的那种
        if mViewConfig.countViewShowType == NBCountViewShowType.FilletButton {
            self.layer.borderColor = mViewConfig.mTintColor.CGColor
            self.layer.borderWidth = 1
            self.layer.cornerRadius = 5
            self.layer.masksToBounds = true
            
            self.lessBtn.layer.borderColor = mViewConfig.mTintColor.CGColor
            self.addBtn.layer.borderColor = mViewConfig.mTintColor.CGColor
            self.lessBtn.layer.borderWidth = 1
            self.addBtn.layer.borderWidth = 1
            
            self.lessBtn.setTitleColor(mViewConfig.mTintColor,forState:.Normal)
            self.addBtn.setTitleColor(mViewConfig.mTintColor,forState:.Normal)
        }else{
            //这是第二种类型,设置圆形按钮
            self.lessBtn.layer.masksToBounds = true
            self.addBtn.layer.masksToBounds = true
            self.lessBtn.layer.cornerRadius = self.frame.size.height / 2.0
            self.addBtn.layer.cornerRadius = self.frame.size.height / 2.0
            
            self.lessBtn.backgroundColor = mViewConfig.mTintColor
            self.addBtn.backgroundColor = mViewConfig.mTintColor
            
            self.lessBtn.setTitleColor(UIColor.whiteColor(),forState: .Normal)
            self.addBtn.setTitleColor(UIColor.whiteColor(),forState: .Normal)
        }
    }
    
    
    /**
    添加约束
    */
    func addAutoLayoutContas(){
        lessBtn.translatesAutoresizingMaskIntoConstraints = false
        addBtn.translatesAutoresizingMaskIntoConstraints = false
        countTextField.translatesAutoresizingMaskIntoConstraints = false
        let viewDicts = dictForViews([lessBtn,countTextField,addBtn])
        
        //设置水平布局,间距5,两个按钮宽度相等
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[lessBtn]-5-[countTextField]-5-[addBtn(lessBtn)]|",options:.DirectionLeadingToTrailing,metrics: nil,views: viewDicts))
        //设置按钮高度
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[lessBtn]|",options:NSLayoutFormatOptions.DirectionLeadingToTrailing,views: viewDicts))
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[countTextField]|",views: viewDicts))
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[addBtn]|",views: viewDicts))
        
        //设置按钮宽高相等
        self.addConstraint(NSLayoutConstraint.init(item:lessBtn,attribute: NSLayoutAttribute.Width,relatedBy: .Equal,toItem: lessBtn,attribute:NSLayoutAttribute.Height,multiplier: 1.0,constant: 0))
    }
    
    /**
    自定义生成键值对dicationary
    - parameter objecs: 数组对象 eg:[1,2,3]
    - returns: 键值对对象 eg:["1":1,"2":2,"3":3]
    */
    func dictForViews(objecs:[AnyObject]) -> [String : AnyObject] {
        var count:UInt32 = 0
        var dicts:[String : AnyObject] = [:]
        let ivars = class_copyIvarList(self.classForCoder,&count)
        for var i = 0; i < Int(count); ++i{
            let obj = object_getIvar(self,ivars[i])
            let name = String.fromCString(ivar_getName(ivars[i]))!
            dicts[name] = obj
            if dicts.count == objecs.count{
                break
            }
        }
        free(ivars)
        return dicts
    }
    /**
    UItextField delegate method
    
    - parameter textField: 就是界面显示当前值的textfield
    
    - returns: 当前textfield是否能编辑,true为可编辑,false为不可编辑
    */
    func textFieldShouldBeginEditing(textField: UITextField) -> Bool{
        return isEditTextField
    }
    /**
    countTextField获取焦点是执行
    
    - parameter textField: <#textField description#>
    */
    func textFieldDidBeginEditing(textField: UITextField){
        //如果开始输入时,为0,就去掉0
        let changedValue = (textField.text! as NSString).integerValue
        if changedValue == 0{
            textField.text = ""
        }
    }
    /**
    countTextField 失去焦点时执行
    
    - parameter textField: <#textField description#>
    */
    func textFieldDidEndEditing(textField: UITextField){
        //如果结束时没有任何输入,就置为0
        if textField.text!.isEmpty{
            textField.text = "0"
        }
    }
    
    
    func textFieldValueChange(textField : UITextField){
        let changedValue = (textField.text! as NSString).integerValue
        let changedStep = changedValue - self.updateAgainValue
        self.mCurrentValue = changedValue
        self.updateAgainValue = self.mCurrentValue
        /**
        回调,传入当前更改的数量
        
        - parameter updateStepValue: 当前更改的数量
        */
        notifyUpdateStepValue?(updateStepValue:changedStep)

    }
    
    /**
    移除焦点事件
    */
    override func resignFirstResponder() -> Bool {
        countTextField.resignFirstResponder()
        return true
    }

}

这上面就是完整的自定义代码,下面,就介绍怎么使用吧,新建一个VC,然后分别创建不同的两种状态的计数器:

如下:

        countView.isEditTextField = true
        self.view.addSubview(countView)
        countView.viewConfig = NBCountConfig(countViewShowType:.FilletButton,tintColor:UIColor.redColor())
        countView.currentValue = 20
        countView.notifyUpdateStepValue = {(updateStepValue : Int) in
            print("更改的数量为:\(updateStepValue)")
        }
        countView.notifyUpdateCurrentValue = {(currentValue : Int) in
            print("当前显示数值为:\(currentValue)")
        }

这里设置了输入框是否可以编辑,以及当前显示值和监听每次更改的值以及当前值等

当然,这只是其中一种状态,还有另一种,如下:

        let countView1 : NBCountView = NBCountView.init(frame: CGRectMake(50,160,120,40))
        self.view.addSubview(countView1)
        
        countView1.viewConfig = NBCountConfig(countViewShowType:.CircleButton,tintColor:UIColor.greenColor())
        countView1.notifyUpdateStepValue = {(updateStepValue : Int) in
            print("更改的数量为:\(updateStepValue)")
        }
        countView1.notifyUpdateCurrentValue = {(currentValue : Int) in
            print("当前显示数值为:\(currentValue)")
        }

这就是两种显示状态的计数器,当然了,如果想要停止编辑,只需要触摸屏幕方法中实现:

    override func touchesBegan(touches: Set<UITouch>,withEvent event: UIEvent?) {
        countView.resignFirstResponder()
    }
 当然了,也不仅仅是这样,根据自己需要调用resignFirstResponder就好了. 
 

以上就是全部代码,如果你也喜欢,可以点个赞,如果你有好的需求,也可以在下面说说.

欢迎赐教,不甚感激!

源码下载:https://github.com/NapoleonBaiAndroid/NBCountView-swift

猜你在找的Swift相关文章