SwiftUI 城市选择器
效果图
//
/*!
-------------------------------------------------------------------------------
File name: CityPicker.swift
Author: lanyuejing
Description: 城市选择器
History:
2023/4/15: File created. at version v版本号
-------------------------------------------------------------------------------
*/
import Foundation
import SwiftUI
import SwiftyJSON
struct CityPicker: View {
// MARK: Internal
var body: some View {
let provinceName = addressItems[safe: selectProvinceIndex]?.name
let city = addressItems[safe: selectProvinceIndex]?.childs[safe: selectCityIndex]?.name
let area = addressItems[safe: selectProvinceIndex]?.childs[safe: selectCityIndex]?.childs[safe: selectAreaIndex]?.name
VStack(spacing: 20) {
HStack {
Text("\(provinceName ?? "未选择")")
Text("\(city ?? "")")
Text("\(area ?? "")")
}.foregroundColor(Color.black)
GeometryReader { geometry in
HStack(spacing: 0) {
Picker("省", selection: $selectProvinceIndex) {
ForEach(0..<addressItems.count, id: \.self) { index in
let name = addressItems[index].name
Text(name)
}
}
.onChange(of: selectProvinceIndex, perform: { _ in
changeSelectCity(selectCityIndex: 0)
})
.frame(width: geometry.size.width/3, alignment: .center)
.clipped()
Picker("市", selection: $selectCityIndex) {
let cities = addressItems[safe: selectProvinceIndex]?.childs
if let cities = cities {
ForEach(0..<cities.count, id: \.self) { index in
let name = cities[safe: index]?.name ?? ""
Text(name)
}
} else {
EmptyView()
}
}
.onChange(of: selectCityIndex, perform: { newValue in
changeSelectAreas(selectCityIndex: newValue)
})
.frame(width: geometry.size.width/3, alignment: .center)
.clipped()
Picker("区", selection: $selectAreaIndex) {
let selectedArea = self.addressItems[safe: selectProvinceIndex]?.childs[safe: selectCityIndex]?.childs
if let areas = selectedArea {
ForEach(0..<areas.count, id: \.self) { index in
let name = areas[safe: index]?.name ?? ""
Text(name)
}
} else {
EmptyView()
}
}
.frame(width: geometry.size.width/3, alignment: .center)
.clipped()
}
}
}.onAppear(perform: { loadAddress() })
}
// MARK: Private
@State private var addressItems: [Province] = []
@State private var selectProvinceIndex = 0
@State private var selectCityIndex = 0
@State private var selectAreaIndex = 0
private func loadAddress() {
let bundle = Bundle.main
let plistPath = bundle.path(forResource: "newaddress", ofType: "plist")
let addressDic = NSDictionary(contentsOfFile: plistPath ?? "") ?? ["": ""]
let jsonData = JSON(addressDic)
let provincesItems = Address(json: jsonData).provinces
addressItems = provincesItems
}
private func changeSelectAreas(selectCityIndex: Int) {
selectAreaIndex = selectCityIndex
}
private func changeSelectCity(selectCityIndex: Int) {
self.selectCityIndex = selectCityIndex
selectAreaIndex = 0
}
}
public extension Collection {
subscript(safe index: Index) -> Element? {
indices.contains(index) ? self[index] : nil
}
}
struct CityPicker_Previews: PreviewProvider {
static var previews: some View {
CityPicker()
}
}
折叠效果之城市选择器
//
/*!
-------------------------------------------------------------------------------
File name: AddressView.swift
Author: langyuejing
Description: 城市选择器
History:
2023/4/15: File created. at version v版本号
-------------------------------------------------------------------------------
*/
import Foundation
import SwiftUI
import SwiftyJSON
struct AddressView: View {
// MARK: Internal
var body: some View {
VStack {
GeometryReader { geometry in
List(addressItems, children: \.childs, selection: $selectionItem, rowContent: { item in
if item.provincecode.count > 0, item.citycode.count > 0 {
Text(item.name).foregroundColor(Color.black).onTapGesture {
selectionItem = item
}.frame(width: geometry.size.width - 40, alignment: .leading).padding(.leading, 80)
} else {
Text(item.name).foregroundColor(Color.black).onTapGesture {
selectionItem = item
}
}
}).onAppear(perform: { loadAddress() })
}
}
}
// MARK: Private
@State private var showAlert = false
@State private var tapValue = "123"
@State private var selectionItem: AreaModel?
@State private var selectProvinceIndex = 0
@State private var selectCityIndex = 0
@State private var selectAreaIndex = 0
@State private var addressItems: [AreaModel] = []
@State private var flags: [Bool] = [false, false, false]
@State private var items: [Any] = []
private func loadAddress() {
let bundle = Bundle.main
let plistPath = bundle.path(forResource: "newaddress", ofType: "plist")
let addressDic = NSDictionary(contentsOfFile: plistPath ?? "") ?? ["": ""]
let jsonData = JSON(addressDic)
let provincesItems = AreaList(json: jsonData).areaList
addressItems = provincesItems
}
}
struct AddressView_Previews: PreviewProvider {
static var previews: some View {
AddressView()
}
}