美文网首页swift
swift-地址选择器

swift-地址选择器

作者: 一蓑丨烟雨 | 来源:发表于2017-09-06 15:28 被阅读38次

    效果图:

    地址选择.png

    定义PickerBaseView

    import UIKit
    
    let kDatePicHeight:CGFloat = 200
    let kTopViewHeight:CGFloat = 44
    
    let SCREEN_BOUNDS = UIScreen.mainBounds
    let SCREEN_WIDTH = UIScreen.mainWidth
    let SCREEN_HEIGHT = UIScreen.mainHeight
    
    class PickerBaseView: UIView {
    
        //背景视图
        lazy var backgroundView:UIView = {
            let view = UIView(frame: SCREEN_BOUNDS)
            view.backgroundColor = UIColor.white.withAlphaComponent(0.20)
            view.isUserInteractionEnabled = true
            let tap = UITapGestureRecognizer(target: self, action: #selector(didTapBackgroundView))
            view.addGestureRecognizer(tap)
            return view
        }()
    
        //弹出视图
        lazy var alertView:UIView = {
            let view = UIView(frame: CGRect(x: 0, y: SCREEN_HEIGHT - kTopViewHeight-kDatePicHeight, width: SCREEN_WIDTH, height: kTopViewHeight+kDatePicHeight))
            view.backgroundColor = UIColor.white
    
            return view
        }()
        
        //顶部视图
        lazy var topView:UIView = {
            let view = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: kTopViewHeight+0.5))
            view.backgroundColor = UIColor.colorWithHexCode(code: "fdfdfd")
            return view
        }()
        
        //左边取消按钮
        lazy var leftBtn:UIButton = {
            let btn = UIButton(type: .custom)
            btn.frame = CGRectMake(5, 8, 60, 28)
            btn.backgroundColor = UIColor.clear
            btn.layer.borderColor = Color.topNav.cgColor
            btn.layer.cornerRadius = 6.0
            btn.layer.masksToBounds = true
            btn.layer.borderWidth = 1.0
            btn.titleLabel?.font = Font.large
            btn.setTitleColor(Color.topNav, for: .normal)
            btn.setTitle("取消", for: .normal)
            btn.addTarget(self, action: #selector(clickLeftBtn), for: .touchUpInside)
            return btn
        }()
        
        //右边确定按钮
        lazy var rightBtn:UIButton = {
            let btn = UIButton(type: .custom)
            btn.frame = CGRectMake(SCREEN_WIDTH - 65, 8, 60, 28)
            btn.backgroundColor = UIColor.clear
            btn.layer.borderColor = Color.topNav.cgColor
            btn.layer.cornerRadius = 6.0
            btn.layer.masksToBounds = true
            btn.layer.borderWidth = 1.0
            btn.titleLabel?.font = Font.large
            btn.setTitleColor(Color.topNav, for: .normal)
            btn.setTitle("确定", for: .normal)
            btn.addTarget(self, action: #selector(clickRightBtn), for: .touchUpInside)
            return btn
    
        }()
        
        //中间标题
        lazy var titleLabel:UILabel = {
            let label = UILabel(frame: CGRectMake(65, 0, SCREEN_WIDTH-130, kTopViewHeight))
            label.backgroundColor = UIColor.clear
            label.font = Font.middleP
            label.textAlignment = .center
            label.textColor = Color.topNav
            return label
        }()
        
        //分割线视图
        lazy var lineView:UIView = {
            let view = UIView(frame: CGRectMake(0, kTopViewHeight, SCREEN_WIDTH, 0.5))
            view.backgroundColor = Color.line2
            return view
        }()
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        func initUI(){
            self.frame = SCREEN_BOUNDS
            
            self.addSubview(self.backgroundView)
            self.addSubview(self.alertView)
            self.alertView.addSubview(self.lineView)
            self.alertView.addSubview(self.topView)
            self.topView.addSubview(self.leftBtn)
            self.topView.addSubview(self.rightBtn)
            self.topView.addSubview(self.titleLabel)
            self.topView.addSubview(self.lineView)
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        
    }
    //响应事件
    extension PickerBaseView{
        func didTapBackgroundView(){
            
        }
        func clickLeftBtn(){
            
        }
        func clickRightBtn(){
            
        }
    
    }
    

    定义PickerView选择器

    import UIKit
    import HandyJSON
    
    typealias AaddressResultBlock = (_ selectedAddress:AddressSelected) -> Void
    
    class AddressPickerView: PickerBaseView{
        
        //初始值
        var rowOfProvince:Int = 0
        var rowOfCity:Int = 0
        var rowOfTown:Int = 0
        
        var textField: UITextField!
        lazy var pickerView:UIPickerView = {
            let pickerV = UIPickerView(frame: CGRectMake(0, kTopViewHeight+0.5, SCREEN_WIDTH, kDatePicHeight))
            pickerV.backgroundColor = UIColor.white
            pickerV.dataSource = self
            pickerV.delegate = self
            return pickerV
        }()
        
        lazy var address:AddressSelected = {
            let are = AddressSelected()
            are.province = "北京市"
            are.city = "北京市辖区"
            are.town = "东城区"
            return are
        }()
        
        var addressModelArr = [AddressProvinceModel]()
        
        var defaultSelectedArr:[Int] = [Int]()
        lazy var isAutoSelect:Bool = true
        
        var resultBlock:AaddressResultBlock?
        
        /// 显示地址选择器
        ///
        /// - Parameters:
        ///   - defaultSelected: 默认选中的值(传数组,元素为对应的索引值)
        ///   - isAutoSelect: 是否自动选择,即选择完执行结果回调,
        ///   - resultBlock: 选择后的回调
        static func showAddressPicker(defaultSelected:[Int], isAutoSelect:Bool, resultBlock:@escaping AaddressResultBlock){
            let addressPickerView = AddressPickerView.pickerView(withDefaultSelectedArr: defaultSelected, isAutoSelect: isAutoSelect, resultBlock: resultBlock)
            addressPickerView.showWithAnimation(animation: true)
        }
        private override init(frame: CGRect) {
            super.init(frame: frame)
        }
        static func pickerView(withDefaultSelectedArr selectedArr:[Int], isAutoSelect autoSelect:Bool, resultBlock:@escaping AaddressResultBlock) -> AddressPickerView {
            let addressPickerView = AddressPickerView()
            if selectedArr.count == 3 {
                addressPickerView.defaultSelectedArr = selectedArr
            }else{
                addressPickerView.defaultSelectedArr = [0,0,0]
            }
            addressPickerView.isAutoSelect = autoSelect
            addressPickerView.resultBlock = resultBlock
            addressPickerView.loadCities()
            addressPickerView.initUI()
            return addressPickerView
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        deinit {
            print("地址选择器被销毁")
        }
        
        //加载城市数据
        func loadCities(){
            let pt = Bundle.main.path(forResource: "Cities.json", ofType: nil)
            let dicp = try?JSONSerialization.jsonObject(with: NSData(contentsOfFile: pt!) as Data, options: .mutableLeaves) as! [String:AnyObject]
            let dicArr = dicp!["data"] as! [AnyObject]
            for dic in dicArr{
                let dicF = dic as! NSDictionary
                let provinceModel = AddressProvinceModel.deserialize(from: dicF)
                addressModelArr.append(provinceModel!)
            }
        }
        
        override func initUI() {
            super.initUI()
            self.titleLabel.text = "请选择城市"
            self.alertView.addSubview(self.pickerView)
        }
    }
    
    extension AddressPickerView{
        //弹出视图方法
        func showWithAnimation(animation:Bool){
            let window = UIApplication.shared.keyWindow
            window?.addSubview(self)
            if animation {
                //动画初始位置
                var rect = self.alertView.frame
                rect.origin.y = SCREEN_HEIGHT
                self.alertView.frame = rect
                //浮现动画
                UIView.animate(withDuration: 0.3, animations: {
                    var rect = self.alertView.frame
                    rect.origin.y -= kDatePicHeight + kTopViewHeight
                    self.alertView.frame = rect
                })
            }
            
            //滚动到默认行
            scrollTo(row: 0, component: 0, animated: true)
        }
        
        //关闭动画
        func dismissWithAnimation(animation:Bool){
            UIView.animate(withDuration: 0.2, animations: {
                var rect = self.alertView.frame
                rect.origin.y += kDatePicHeight+kTopViewHeight
                self.alertView.frame = rect
                self.backgroundView.alpha = 0
            }) { (finished) in
                self.leftBtn.removeFromSuperview()
                self.rightBtn.removeFromSuperview()
                self.titleLabel.removeFromSuperview()
                self.lineView.removeFromSuperview()
                self.topView.removeFromSuperview()
                self.pickerView.removeFromSuperview()
                self.alertView.removeFromSuperview()
                self.backgroundView.removeFromSuperview()
                self.removeFromSuperview()
            }
        }
        override func clickLeftBtn() {
            self.dismissWithAnimation(animation: true)
        }
        override func clickRightBtn() {
            self.dismissWithAnimation(animation: true)
            if (self.resultBlock != nil) {
                self.resultBlock!(address)
            }
        }
        override func didTapBackgroundView() {
            self.dismissWithAnimation(animation: false)
        }
    }
    
    extension AddressPickerView: UIPickerViewDelegate, UIPickerViewDataSource {
        
        func numberOfComponents(in pickerView: UIPickerView) -> Int {
            return 3
        }
        
        func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            let provinceModel = self.addressModelArr[rowOfProvince];
            let cityModel = provinceModel.city?[rowOfCity];
            if (component == 0) {
                //返回省个数
                return self.addressModelArr.count;
            }
            if (component == 1) {
                //返回市个数
                return provinceModel.city?.count ?? 1;
            }
            if (component == 2) {
                //返回区个数
                return cityModel?.town?.count ?? 1;
            }
            return 0;
        }
        
        //row
        func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
            var showTitleValue:String = ""
            switch component {
            case 0:
                let provinceModel = addressModelArr[row]
                showTitleValue = provinceModel.name!
                break
            case 1:
                let provinceModel = addressModelArr[rowOfProvince]
                let cityModel = provinceModel.city?[row]
                showTitleValue = cityModel?.name ?? ""
                break
            case 2:
                let provinceModel = addressModelArr[rowOfProvince]
                let cityModel = provinceModel.city?[rowOfCity]
                let towModel = cityModel?.town?[row]
                showTitleValue = towModel?.name ?? ""
                break
            default:
                break
            }
            return showTitleValue
        }
        
        //自定义cell
        func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: (UIScreen.mainWidth-30)/3, height: 40))
            label.textAlignment = .center
            label.font = Font.largeP
            label.text = self.pickerView(pickerView, titleForRow: row, forComponent: component)
            return label
        }
        
        //选中
        func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            if (component == 0) {
                rowOfProvince = row;
                rowOfCity = 0;
                rowOfTown = 0;
                address.province = addressModelArr[rowOfProvince].name!
            } else if (component == 1) {
                rowOfCity = row;
                rowOfTown = 0;
                address.city = addressModelArr[rowOfProvince].city![rowOfCity].name!
                
            } else if (component == 2) {
                rowOfTown = row;
                address.town = addressModelArr[rowOfProvince].city![rowOfCity].town![rowOfTown].name!
            }
            scrollTo(row: row, component: component)
            
            if self.isAutoSelect {
                self.resultBlock!(address)
            }
            
        }
        //MARK: - 手动滚动刷新
        func scrollTo(row:Int, component:Int, animated:Bool = true){
            self.pickerView.selectRow(row, inComponent: component, animated: animated)
            switch component {
            case 0:
                rowOfProvince = row
                rowOfCity = 0
                rowOfTown = 0
                let provinceModel = addressModelArr[row]
                address.province = provinceModel.name!
                let cityModel = provinceModel.city?[rowOfCity]
                address.city = cityModel?.name ?? ""
                address.town = cityModel?.town?[rowOfTown].name ?? ""
                pickerView.reloadComponent(1)
                pickerView.reloadComponent(2)
                break
            case 1:
                rowOfCity = row
                rowOfTown = 0
                self.pickerView.reloadComponent(2)
                let cityModel = addressModelArr[rowOfProvince].city?[row]
                address.city = cityModel?.name ?? ""
                address.town = cityModel?.town?[rowOfTown].name ?? ""
                break
            case 2:
                rowOfTown = row
                address.town = addressModelArr[rowOfProvince].city?[rowOfCity].town?[row].name ?? ""
                break
            default:
                break
            }
            pickerView.selectRow(rowOfProvince, inComponent: 0, animated: true)
            pickerView.selectRow(rowOfCity, inComponent: 1, animated: true)
            pickerView.selectRow(rowOfTown, inComponent: 2, animated: true)
            /*
            if self.isAutoSelect {
                self.resultBlock!(address)
            }
            */
        }
        
    }
    
    
    //MARK: - 地址数据模型
    class AddressProvinceModel:HandyJSON{
        var name:String?
        var city:[AddressCityModel]?
        required init() {
        }
        func mapping(mapper: HelpingMapper) {
            
            mapper <<<
                self.city <-- "children"
            
        }
        
    }
    
    class AddressCityModel:HandyJSON{
        var name:String?
        var town:[AddressTownModel]?
        required init() {}
        func mapping(mapper: HelpingMapper) {
            
            mapper <<<
                self.town <-- "children"
        }
    }
    class AddressTownModel:HandyJSON{
        var name:String?
        required init() {}
        
    }
    //记录选中的区域
    class AddressSelected {
        var province = ""
        var city = ""
        var town = ""
        
        func description(){
            
        }
    }
    
    //MARK:- 自定义TextField
    typealias SelectTapActionBlock = ()->Void
    
    class TapTextField: UITextField {
        
        var tapActionBlock:SelectTapActionBlock?
        
     @IBInspectable
        var leftStr: String!
        var leftMoreW: CGFloat = 0
        
        lazy var tapView = { () -> UIView in 
            let tapV = UIView()
            tapV.backgroundColor = UIColor.clear
            let tap = UITapGestureRecognizer(target: self, action: #selector(didTapAction))
            tapV.addGestureRecognizer(tap)
            tapV.isUserInteractionEnabled = true
            return tapV
        }()
        
        override func draw(_ rect: CGRect) {
            super.draw(rect)
            if self.leftStr != nil{
                let leftLabel = UILabel()
                leftLabel.frame = CGRect(x: 15, y: 0, width: 100, height: rect.height)
                leftLabel.text = self.leftStr
                leftLabel.textColor = Color.textH
                leftLabel.font = Font.large
                
                let leftView = UIView()
                leftView.frame = CGRect(x: 0, y: 0, width: leftLabel.sizeWidth+25+self.leftMoreW, height: rect.height)
                self.leftView = leftView
                self.leftViewMode = UITextFieldViewMode.always
                leftView.addSubview(leftLabel)
            }else{
                self.addLeftBlank(w: 15)
            }
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.addSubview(tapView)
        }
        convenience init() {
            self.init(frame: CGRect.zero)
            self.backgroundColor = UIColor.white
            self.textColor = Color.textM
        }
        override func layoutSubviews() {
            super.layoutSubviews()
            self.tapView.snp.makeConstraints { (make) in
                make.edges.equalToSuperview()
            }
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        func setTapActionBlock(actionBlock:@escaping SelectTapActionBlock){
            self.tapActionBlock = actionBlock
            self.tapView.isHidden = false
        }
        func didTapAction(){
            //响应点击事件,隐藏键盘
    //        UIApplication.shared.keyWindow?.endEditing(true)
            self.tapActionBlock!()
        }
    }
    
    
    

    使用说明:

         //显示地址
        lazy var addressTextField:TapTextField = {
            let label = TapTextField()
            label.leftStr = "所在地区"
            label.placeholder = "请选择"
            label.delegate = self
            label.textAlignment = .right
    
            return label
        }()
    
        
            addressTextField.setTapActionBlock(actionBlock: {
            AddressPickerView.showAddressPicker(defaultSelected: [0,0,0], isAutoSelect: true, resultBlock: { [unowned self](selectedAddress) in
                self.setAreaText(address: selectedAddress)
                })
            })
    

    相关文章

      网友评论

        本文标题:swift-地址选择器

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