210 lines
7.7 KiB
Swift
210 lines
7.7 KiB
Swift
//
|
|
// PaymentSetAmountDialogView.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import SnapKit
|
|
import UIKit
|
|
|
|
/// 设置收款金额弹窗,对齐 Android `SetAmountDialog`。
|
|
final class PaymentSetAmountDialogView: KeyboardAvoidingDialogView {
|
|
|
|
var onConfirm: (() -> Void)?
|
|
var onCancel: (() -> Void)?
|
|
var onAmountChange: ((String) -> Void)?
|
|
var onRemarkChange: ((String) -> Void)?
|
|
|
|
private let dimView = UIView()
|
|
private let cardView = UIView()
|
|
private let titleLabel = UILabel()
|
|
private let amountContainer = UIView()
|
|
private let currencyLabel = UILabel()
|
|
private let amountField = UITextField()
|
|
private let remarkTitleLabel = UILabel()
|
|
private let remarkField = UITextView()
|
|
private let remarkCountLabel = UILabel()
|
|
private let buttonStack = UIStackView()
|
|
private let cancelButton = UIButton(type: .system)
|
|
private let confirmButton = UIButton(type: .system)
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
setupUI()
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func apply(amount: String, remark: String) {
|
|
if amountField.text != amount {
|
|
amountField.text = amount
|
|
}
|
|
if remarkField.text != remark {
|
|
remarkField.text = remark
|
|
}
|
|
remarkCountLabel.text = "\(remark.count)/200"
|
|
}
|
|
|
|
func show(in parent: UIView) {
|
|
frame = parent.bounds
|
|
autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
alpha = 0
|
|
parent.addSubview(self)
|
|
layoutIfNeeded()
|
|
amountField.becomeFirstResponder()
|
|
UIView.animate(withDuration: 0.2) {
|
|
self.alpha = 1
|
|
}
|
|
}
|
|
|
|
func dismiss() {
|
|
endEditing(true)
|
|
UIView.animate(withDuration: 0.2, animations: {
|
|
self.alpha = 0
|
|
}, completion: { _ in
|
|
self.removeFromSuperview()
|
|
})
|
|
}
|
|
|
|
private func setupUI() {
|
|
keyboardAvoidingContentView = cardView
|
|
|
|
dimView.backgroundColor = AppColor.overlayScrim
|
|
dimView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(cancelTapped)))
|
|
|
|
cardView.backgroundColor = .white
|
|
cardView.layer.cornerRadius = AppRadius.xl
|
|
cardView.clipsToBounds = true
|
|
|
|
titleLabel.text = "收款金额"
|
|
titleLabel.font = .systemFont(ofSize: 18, weight: .bold)
|
|
titleLabel.textColor = AppColor.textPrimary
|
|
|
|
amountContainer.backgroundColor = AppColor.inputBackground
|
|
amountContainer.layer.cornerRadius = AppRadius.sm
|
|
|
|
currencyLabel.text = "¥"
|
|
currencyLabel.font = .systemFont(ofSize: 20, weight: .bold)
|
|
currencyLabel.textColor = AppColor.textPrimary
|
|
|
|
amountField.placeholder = "请输入收款金额"
|
|
amountField.font = .systemFont(ofSize: 18, weight: .medium)
|
|
amountField.keyboardType = .decimalPad
|
|
amountField.borderStyle = .none
|
|
amountField.backgroundColor = .clear
|
|
amountField.addTarget(self, action: #selector(amountChanged), for: .editingChanged)
|
|
|
|
remarkTitleLabel.text = "备注 (选填)"
|
|
remarkTitleLabel.font = .systemFont(ofSize: 14)
|
|
remarkTitleLabel.textColor = UIColor(hex: 0x4B5563)
|
|
|
|
remarkField.font = .systemFont(ofSize: 14)
|
|
remarkField.textColor = AppColor.textPrimary
|
|
remarkField.backgroundColor = .white
|
|
remarkField.layer.borderColor = UIColor(hex: 0xE5E7EB).cgColor
|
|
remarkField.layer.borderWidth = 1
|
|
remarkField.layer.cornerRadius = AppRadius.sm
|
|
remarkField.textContainerInset = UIEdgeInsets(top: 10, left: 8, bottom: 10, right: 8)
|
|
remarkField.delegate = self
|
|
|
|
remarkCountLabel.font = .systemFont(ofSize: 12)
|
|
remarkCountLabel.textColor = AppColor.textTertiary
|
|
remarkCountLabel.textAlignment = .right
|
|
remarkCountLabel.text = "0/200"
|
|
|
|
buttonStack.axis = .horizontal
|
|
buttonStack.spacing = AppSpacing.sm
|
|
buttonStack.distribution = .fillEqually
|
|
|
|
cancelButton.setTitle("取消", for: .normal)
|
|
cancelButton.setTitleColor(AppColor.textSecondary, for: .normal)
|
|
cancelButton.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
|
cancelButton.backgroundColor = AppColor.inputBackground
|
|
cancelButton.layer.cornerRadius = AppRadius.sm
|
|
cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
|
|
|
|
confirmButton.setTitle("确定", for: .normal)
|
|
confirmButton.setTitleColor(.white, for: .normal)
|
|
confirmButton.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
|
confirmButton.backgroundColor = AppColor.primary
|
|
confirmButton.layer.cornerRadius = AppRadius.sm
|
|
confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
|
|
|
|
addSubview(dimView)
|
|
addSubview(cardView)
|
|
cardView.addSubview(titleLabel)
|
|
cardView.addSubview(amountContainer)
|
|
amountContainer.addSubview(currencyLabel)
|
|
amountContainer.addSubview(amountField)
|
|
cardView.addSubview(remarkTitleLabel)
|
|
cardView.addSubview(remarkField)
|
|
cardView.addSubview(remarkCountLabel)
|
|
cardView.addSubview(buttonStack)
|
|
buttonStack.addArrangedSubview(cancelButton)
|
|
buttonStack.addArrangedSubview(confirmButton)
|
|
|
|
dimView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
cardView.snp.makeConstraints { make in
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
keyboardAvoidingCenterYConstraint = make.centerY.equalToSuperview().constraint
|
|
}
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.top.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
}
|
|
amountContainer.snp.makeConstraints { make in
|
|
make.top.equalTo(titleLabel.snp.bottom).offset(20)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(48)
|
|
}
|
|
currencyLabel.snp.makeConstraints { make in
|
|
make.leading.equalToSuperview().offset(AppSpacing.sm)
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
amountField.snp.makeConstraints { make in
|
|
make.leading.equalTo(currencyLabel.snp.trailing).offset(AppSpacing.xs)
|
|
make.trailing.equalToSuperview().inset(AppSpacing.sm)
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
remarkTitleLabel.snp.makeConstraints { make in
|
|
make.top.equalTo(amountContainer.snp.bottom).offset(AppSpacing.md)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
}
|
|
remarkField.snp.makeConstraints { make in
|
|
make.top.equalTo(remarkTitleLabel.snp.bottom).offset(AppSpacing.xs)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(100)
|
|
}
|
|
remarkCountLabel.snp.makeConstraints { make in
|
|
make.top.equalTo(remarkField.snp.bottom).offset(AppSpacing.xxs)
|
|
make.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
}
|
|
buttonStack.snp.makeConstraints { make in
|
|
make.top.equalTo(remarkCountLabel.snp.bottom).offset(AppSpacing.lg)
|
|
make.leading.trailing.bottom.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(44)
|
|
}
|
|
}
|
|
|
|
@objc private func amountChanged() {
|
|
onAmountChange?(amountField.text ?? "")
|
|
}
|
|
|
|
@objc private func cancelTapped() {
|
|
onCancel?()
|
|
}
|
|
|
|
@objc private func confirmTapped() {
|
|
onConfirm?()
|
|
}
|
|
}
|
|
|
|
extension PaymentSetAmountDialogView: UITextViewDelegate {
|
|
func textViewDidChange(_ textView: UITextView) {
|
|
onRemarkChange?(textView.text ?? "")
|
|
}
|
|
}
|