628 lines
22 KiB
Swift
628 lines
22 KiB
Swift
//
|
|
// TaskAddViews.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Kingfisher
|
|
import SnapKit
|
|
import UIKit
|
|
|
|
/// 添加任务素材网格区。
|
|
final class TaskAddMediaSectionView: UIView {
|
|
|
|
var onCloudImport: (() -> Void)?
|
|
var onLocalImport: (() -> Void)?
|
|
var onFileTap: ((TaskFileItem) -> Void)?
|
|
var onDeleteFile: ((TaskFileItem) -> Void)?
|
|
|
|
private var files: [TaskFileItem] = []
|
|
private var collectionHeightConstraint: Constraint?
|
|
|
|
private enum Section { case main }
|
|
private enum Item: Hashable { case add; case file(String) }
|
|
|
|
private lazy var collectionView: UICollectionView = {
|
|
let layout = UICollectionViewCompositionalLayout { _, environment in
|
|
let columns = 3
|
|
let spacing: CGFloat = 8
|
|
let inset = AppSpacing.md * 2
|
|
let availableWidth = environment.container.effectiveContentSize.width - inset
|
|
let totalSpacing = spacing * CGFloat(columns - 1)
|
|
let itemWidth = max(0, (availableWidth - totalSpacing) / CGFloat(columns))
|
|
let itemHeight = itemWidth / 1.77
|
|
let itemSize = NSCollectionLayoutSize(
|
|
widthDimension: .absolute(itemWidth),
|
|
heightDimension: .absolute(itemHeight)
|
|
)
|
|
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
|
let groupSize = NSCollectionLayoutSize(
|
|
widthDimension: .fractionalWidth(1),
|
|
heightDimension: .absolute(itemHeight)
|
|
)
|
|
let group = NSCollectionLayoutGroup.horizontal(
|
|
layoutSize: groupSize,
|
|
repeatingSubitem: item,
|
|
count: columns
|
|
)
|
|
group.interItemSpacing = .fixed(spacing)
|
|
let section = NSCollectionLayoutSection(group: group)
|
|
section.interGroupSpacing = spacing
|
|
return section
|
|
}
|
|
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
|
view.backgroundColor = .clear
|
|
view.isScrollEnabled = false
|
|
return view
|
|
}()
|
|
|
|
private lazy var dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) {
|
|
[weak self] collectionView, indexPath, item in
|
|
switch item {
|
|
case .add:
|
|
let cell = collectionView.dequeueReusableCell(
|
|
withReuseIdentifier: TaskAddAddMediaCell.reuseIdentifier,
|
|
for: indexPath
|
|
) as! TaskAddAddMediaCell
|
|
return cell
|
|
case .file(let id):
|
|
let cell = collectionView.dequeueReusableCell(
|
|
withReuseIdentifier: TaskAddMediaCell.reuseIdentifier,
|
|
for: indexPath
|
|
) as! TaskAddMediaCell
|
|
if let file = self?.files.first(where: { $0.id == id }) {
|
|
cell.apply(file: file)
|
|
cell.onDelete = { self?.onDeleteFile?(file) }
|
|
}
|
|
return cell
|
|
}
|
|
}
|
|
|
|
private let titleLabel = UILabel()
|
|
private let tipsLabel = UILabel()
|
|
private let cloudButton = UIButton(type: .system)
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = AppRadius.md
|
|
|
|
titleLabel.text = "添加图片"
|
|
titleLabel.font = .app(.bodyMedium)
|
|
titleLabel.textColor = AppColor.textPrimary
|
|
|
|
tipsLabel.text = "(点击图片或视频可添加备注)"
|
|
tipsLabel.font = .app(.caption)
|
|
tipsLabel.textColor = AppColor.textPrimary
|
|
|
|
cloudButton.setTitle("云盘导入", for: .normal)
|
|
cloudButton.setTitleColor(AppColor.primary, for: .normal)
|
|
cloudButton.titleLabel?.font = .app(.caption)
|
|
cloudButton.addTarget(self, action: #selector(cloudTapped), for: .touchUpInside)
|
|
|
|
collectionView.register(TaskAddMediaCell.self, forCellWithReuseIdentifier: TaskAddMediaCell.reuseIdentifier)
|
|
collectionView.register(TaskAddAddMediaCell.self, forCellWithReuseIdentifier: TaskAddAddMediaCell.reuseIdentifier)
|
|
collectionView.delegate = self
|
|
|
|
addSubview(titleLabel)
|
|
addSubview(tipsLabel)
|
|
addSubview(cloudButton)
|
|
addSubview(collectionView)
|
|
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.top.leading.equalToSuperview().offset(AppSpacing.md)
|
|
}
|
|
tipsLabel.snp.makeConstraints { make in
|
|
make.leading.equalTo(titleLabel.snp.trailing).offset(AppSpacing.xxs)
|
|
make.centerY.equalTo(titleLabel)
|
|
}
|
|
cloudButton.snp.makeConstraints { make in
|
|
make.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.centerY.equalTo(titleLabel)
|
|
}
|
|
collectionView.snp.makeConstraints { make in
|
|
make.top.equalTo(titleLabel.snp.bottom).offset(AppSpacing.sm)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.bottom.equalToSuperview().inset(AppSpacing.md)
|
|
collectionHeightConstraint = make.height.equalTo(88).constraint
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func apply(files: [TaskFileItem]) {
|
|
self.files = files
|
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
|
snapshot.appendSections([.main])
|
|
snapshot.appendItems(files.map { Item.file($0.id) } + [.add])
|
|
dataSource.apply(snapshot, animatingDifferences: false)
|
|
collectionView.layoutIfNeeded()
|
|
let height = max(88, collectionView.collectionViewLayout.collectionViewContentSize.height)
|
|
collectionHeightConstraint?.update(offset: height)
|
|
}
|
|
|
|
@objc private func cloudTapped() {
|
|
onCloudImport?()
|
|
}
|
|
}
|
|
|
|
extension TaskAddMediaSectionView: UICollectionViewDelegate {
|
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
|
|
switch item {
|
|
case .add:
|
|
onLocalImport?()
|
|
case .file(let id):
|
|
guard let file = files.first(where: { $0.id == id }) else { return }
|
|
onFileTap?(file)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 素材缩略图 cell。
|
|
final class TaskAddMediaCell: UICollectionViewCell {
|
|
|
|
static let reuseIdentifier = "TaskAddMediaCell"
|
|
|
|
var onDelete: (() -> Void)?
|
|
|
|
private let imageView = UIImageView()
|
|
private let overlayView = UIView()
|
|
private let progressLabel = UILabel()
|
|
private let deleteButton = UIButton(type: .system)
|
|
private let playIconView = UIImageView()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
contentView.backgroundColor = AppColor.inputBackground
|
|
contentView.layer.cornerRadius = AppRadius.sm
|
|
contentView.clipsToBounds = true
|
|
|
|
imageView.contentMode = .scaleAspectFill
|
|
imageView.clipsToBounds = true
|
|
|
|
overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.35)
|
|
overlayView.isHidden = true
|
|
|
|
progressLabel.font = .app(.captionMedium)
|
|
progressLabel.textColor = .white
|
|
progressLabel.textAlignment = .center
|
|
|
|
deleteButton.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
|
|
deleteButton.tintColor = .white
|
|
deleteButton.addTarget(self, action: #selector(deleteTapped), for: .touchUpInside)
|
|
|
|
playIconView.image = UIImage(systemName: "play.circle.fill")
|
|
playIconView.tintColor = .white
|
|
playIconView.isHidden = true
|
|
|
|
contentView.addSubview(imageView)
|
|
contentView.addSubview(overlayView)
|
|
contentView.addSubview(playIconView)
|
|
contentView.addSubview(progressLabel)
|
|
contentView.addSubview(deleteButton)
|
|
|
|
imageView.snp.makeConstraints { make in make.edges.equalToSuperview() }
|
|
overlayView.snp.makeConstraints { make in make.edges.equalToSuperview() }
|
|
playIconView.snp.makeConstraints { make in
|
|
make.center.equalToSuperview()
|
|
make.width.height.equalTo(28)
|
|
}
|
|
progressLabel.snp.makeConstraints { make in make.center.equalToSuperview() }
|
|
deleteButton.snp.makeConstraints { make in
|
|
make.top.trailing.equalToSuperview().inset(AppSpacing.xxs)
|
|
make.width.height.equalTo(22)
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func prepareForReuse() {
|
|
super.prepareForReuse()
|
|
onDelete = nil
|
|
imageView.kf.cancelDownloadTask()
|
|
imageView.image = nil
|
|
}
|
|
|
|
func apply(file: TaskFileItem) {
|
|
let urlString = file.previewURLString
|
|
if let url = URL(string: urlString), !urlString.isEmpty {
|
|
imageView.kf.setImage(with: url)
|
|
} else {
|
|
imageView.image = UIImage(systemName: "photo")
|
|
imageView.tintColor = AppColor.textTertiary
|
|
}
|
|
playIconView.isHidden = file.fileType != 1
|
|
if file.isUploading {
|
|
overlayView.isHidden = false
|
|
progressLabel.text = "\(file.uploadProgress)%"
|
|
} else {
|
|
overlayView.isHidden = true
|
|
progressLabel.text = nil
|
|
}
|
|
}
|
|
|
|
@objc private func deleteTapped() {
|
|
onDelete?()
|
|
}
|
|
}
|
|
|
|
/// 本地导入占位 cell。
|
|
final class TaskAddAddMediaCell: UICollectionViewCell {
|
|
|
|
static let reuseIdentifier = "TaskAddAddMediaCell"
|
|
|
|
private let iconView = UIImageView()
|
|
private let titleLabel = UILabel()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
contentView.backgroundColor = AppColor.inputBackground
|
|
contentView.layer.cornerRadius = AppRadius.sm
|
|
|
|
iconView.image = UIImage(systemName: "plus")
|
|
iconView.tintColor = AppColor.textTabInactive
|
|
|
|
titleLabel.text = "本地导入"
|
|
titleLabel.font = .app(.caption)
|
|
titleLabel.textColor = AppColor.textTabInactive
|
|
|
|
contentView.addSubview(iconView)
|
|
contentView.addSubview(titleLabel)
|
|
iconView.snp.makeConstraints { make in
|
|
make.centerX.equalToSuperview()
|
|
make.centerY.equalToSuperview().offset(-8)
|
|
make.width.height.equalTo(24)
|
|
}
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.top.equalTo(iconView.snp.bottom).offset(2)
|
|
make.centerX.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
|
|
/// 任务优先级选择区。
|
|
final class TaskPrioritySectionView: UIView {
|
|
|
|
var onUrgentHourChange: ((Int) -> Void)?
|
|
var onCustomHourTextChange: ((String) -> Void)?
|
|
|
|
private let titleLabel = UILabel()
|
|
private let noneButton = UIButton(type: .system)
|
|
private let twoHourButton = UIButton(type: .system)
|
|
private let customButton = UIButton(type: .system)
|
|
private let customField = UITextField()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = AppRadius.md
|
|
|
|
titleLabel.text = "优先级"
|
|
titleLabel.font = .app(.bodyMedium)
|
|
titleLabel.textColor = AppColor.textPrimary
|
|
|
|
configureOptionButton(noneButton, title: "不加急")
|
|
configureOptionButton(twoHourButton, title: "加急(2小时)")
|
|
configureOptionButton(customButton, title: "自定义")
|
|
|
|
noneButton.addTarget(self, action: #selector(noneTapped), for: .touchUpInside)
|
|
twoHourButton.addTarget(self, action: #selector(twoHourTapped), for: .touchUpInside)
|
|
customButton.addTarget(self, action: #selector(customTapped), for: .touchUpInside)
|
|
|
|
customField.placeholder = "请输入小时数"
|
|
customField.font = .app(.body)
|
|
customField.textColor = AppColor.textPrimary
|
|
customField.keyboardType = .numberPad
|
|
customField.borderStyle = .roundedRect
|
|
customField.isHidden = true
|
|
customField.addTarget(self, action: #selector(customFieldChanged), for: .editingChanged)
|
|
|
|
let row = UIStackView(arrangedSubviews: [noneButton, twoHourButton, customButton])
|
|
row.axis = .horizontal
|
|
row.spacing = AppSpacing.xs
|
|
row.distribution = .fillEqually
|
|
|
|
addSubview(titleLabel)
|
|
addSubview(row)
|
|
addSubview(customField)
|
|
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.top.leading.equalToSuperview().offset(AppSpacing.md)
|
|
}
|
|
row.snp.makeConstraints { make in
|
|
make.top.equalTo(titleLabel.snp.bottom).offset(AppSpacing.sm)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(42)
|
|
}
|
|
customField.snp.makeConstraints { make in
|
|
make.top.equalTo(row.snp.bottom).offset(AppSpacing.sm)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.bottom.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(40)
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func apply(urgentHour: Int) {
|
|
let isCustom = urgentHour > 0 && urgentHour != 2
|
|
styleOption(noneButton, selected: urgentHour == 0)
|
|
styleOption(twoHourButton, selected: urgentHour == 2)
|
|
styleOption(customButton, selected: isCustom)
|
|
customField.isHidden = !isCustom
|
|
if isCustom {
|
|
customField.text = "\(urgentHour)"
|
|
} else {
|
|
customField.text = ""
|
|
}
|
|
}
|
|
|
|
private func configureOptionButton(_ button: UIButton, title: String) {
|
|
button.setTitle(title, for: .normal)
|
|
button.titleLabel?.font = .app(.caption)
|
|
button.layer.cornerRadius = AppRadius.xs
|
|
button.clipsToBounds = true
|
|
}
|
|
|
|
private func styleOption(_ button: UIButton, selected: Bool) {
|
|
button.backgroundColor = selected ? AppColor.primary : AppColor.inputBackground
|
|
button.setTitleColor(selected ? .white : AppColor.textSecondary, for: .normal)
|
|
}
|
|
|
|
@objc private func noneTapped() { onUrgentHourChange?(0) }
|
|
@objc private func twoHourTapped() { onUrgentHourChange?(2) }
|
|
@objc private func customTapped() {
|
|
onUrgentHourChange?(1)
|
|
onCustomHourTextChange?("1")
|
|
}
|
|
@objc private func customFieldChanged() {
|
|
onCustomHourTextChange?(customField.text ?? "")
|
|
}
|
|
}
|
|
|
|
/// 关联订单选择按钮。
|
|
final class TaskOrderSelectButton: UIControl {
|
|
|
|
private let titleLabel = UILabel()
|
|
private let arrowView = UIImageView(image: UIImage(systemName: "chevron.down"))
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = AppRadius.sm
|
|
layer.borderWidth = 1
|
|
layer.borderColor = AppColor.border.cgColor
|
|
|
|
titleLabel.font = .app(.bodyMedium)
|
|
titleLabel.textColor = AppColor.textTabInactive
|
|
titleLabel.text = "关联订单(可选)"
|
|
|
|
arrowView.tintColor = AppColor.textTabInactive
|
|
|
|
addSubview(titleLabel)
|
|
addSubview(arrowView)
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.leading.equalToSuperview().offset(AppSpacing.sm)
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
arrowView.snp.makeConstraints { make in
|
|
make.trailing.equalToSuperview().inset(AppSpacing.sm)
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
snp.makeConstraints { make in make.height.equalTo(44) }
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func apply(orderNumber: String?) {
|
|
if let orderNumber, !orderNumber.isEmpty {
|
|
titleLabel.text = orderNumber
|
|
titleLabel.textColor = AppColor.textPrimary
|
|
} else {
|
|
titleLabel.text = "关联订单(可选)"
|
|
titleLabel.textColor = AppColor.textTabInactive
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 任务素材备注弹窗。
|
|
final class TaskFileRemarkDialogView: UIView {
|
|
|
|
var onCancel: (() -> Void)?
|
|
var onConfirm: (() -> Void)?
|
|
|
|
private let containerView = UIView()
|
|
private let titleLabel = UILabel()
|
|
private let previewView = UIImageView()
|
|
private let textView = UITextView()
|
|
private let countLabel = UILabel()
|
|
private let cancelButton = UIButton(type: .system)
|
|
private let confirmButton = UIButton(type: .system)
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = AppColor.overlayScrim
|
|
|
|
containerView.backgroundColor = .white
|
|
containerView.layer.cornerRadius = AppRadius.md
|
|
|
|
titleLabel.text = "备注信息"
|
|
titleLabel.font = .app(.title)
|
|
|
|
previewView.contentMode = .scaleAspectFill
|
|
previewView.clipsToBounds = true
|
|
previewView.layer.cornerRadius = AppRadius.sm
|
|
previewView.backgroundColor = AppColor.inputBackground
|
|
|
|
textView.font = .app(.body)
|
|
textView.layer.borderWidth = 1
|
|
textView.layer.borderColor = AppColor.border.cgColor
|
|
textView.layer.cornerRadius = AppRadius.sm
|
|
textView.delegate = self
|
|
|
|
countLabel.font = .app(.caption)
|
|
countLabel.textColor = AppColor.textTertiary
|
|
countLabel.text = "0/50"
|
|
|
|
cancelButton.setTitle("取消", for: .normal)
|
|
cancelButton.setTitleColor(AppColor.textSecondary, for: .normal)
|
|
cancelButton.backgroundColor = AppColor.inputBackground
|
|
cancelButton.layer.cornerRadius = AppRadius.xs
|
|
cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
|
|
|
|
confirmButton.setTitle("确定", for: .normal)
|
|
confirmButton.setTitleColor(.white, for: .normal)
|
|
confirmButton.backgroundColor = AppColor.primary
|
|
confirmButton.layer.cornerRadius = AppRadius.xs
|
|
confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
|
|
|
|
addSubview(containerView)
|
|
containerView.addSubview(titleLabel)
|
|
containerView.addSubview(previewView)
|
|
containerView.addSubview(textView)
|
|
containerView.addSubview(countLabel)
|
|
containerView.addSubview(cancelButton)
|
|
containerView.addSubview(confirmButton)
|
|
|
|
containerView.snp.makeConstraints { make in
|
|
make.center.equalToSuperview()
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.lg)
|
|
}
|
|
titleLabel.snp.makeConstraints { make in
|
|
make.top.leading.equalToSuperview().offset(AppSpacing.md)
|
|
}
|
|
previewView.snp.makeConstraints { make in
|
|
make.top.equalTo(titleLabel.snp.bottom).offset(AppSpacing.sm)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(160)
|
|
}
|
|
textView.snp.makeConstraints { make in
|
|
make.top.equalTo(previewView.snp.bottom).offset(AppSpacing.sm)
|
|
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(80)
|
|
}
|
|
countLabel.snp.makeConstraints { make in
|
|
make.top.equalTo(textView.snp.bottom).offset(AppSpacing.xxs)
|
|
make.trailing.equalTo(textView)
|
|
}
|
|
cancelButton.snp.makeConstraints { make in
|
|
make.top.equalTo(countLabel.snp.bottom).offset(AppSpacing.md)
|
|
make.leading.bottom.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(36)
|
|
make.width.equalTo(72)
|
|
}
|
|
confirmButton.snp.makeConstraints { make in
|
|
make.centerY.equalTo(cancelButton)
|
|
make.trailing.equalToSuperview().inset(AppSpacing.md)
|
|
make.height.equalTo(36)
|
|
make.width.equalTo(72)
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func apply(file: TaskFileItem, text: String) {
|
|
textView.text = text
|
|
countLabel.text = "\(text.count)/50"
|
|
let urlString = file.previewURLString
|
|
if let url = URL(string: urlString), !urlString.isEmpty {
|
|
previewView.kf.setImage(with: url)
|
|
} else {
|
|
previewView.image = UIImage(systemName: "photo")
|
|
previewView.tintColor = AppColor.textTertiary
|
|
}
|
|
}
|
|
|
|
@objc private func cancelTapped() { onCancel?() }
|
|
@objc private func confirmTapped() { onConfirm?() }
|
|
|
|
/// 当前输入的备注文本。
|
|
var inputText: String { textView.text ?? "" }
|
|
}
|
|
|
|
extension TaskFileRemarkDialogView: UITextViewDelegate {
|
|
func textViewDidChange(_ textView: UITextView) {
|
|
if textView.text.count > 50 {
|
|
textView.text = String(textView.text.prefix(50))
|
|
}
|
|
countLabel.text = "\(textView.text.count)/50"
|
|
}
|
|
}
|
|
|
|
/// 带边框的单行输入框。
|
|
final class TaskBorderTextField: UIView {
|
|
|
|
let textField = UITextField()
|
|
|
|
init(placeholder: String) {
|
|
super.init(frame: .zero)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = AppRadius.sm
|
|
layer.borderWidth = 1
|
|
layer.borderColor = AppColor.border.cgColor
|
|
|
|
textField.placeholder = placeholder
|
|
textField.font = .app(.body)
|
|
textField.textColor = AppColor.textPrimary
|
|
addSubview(textField)
|
|
textField.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 10, left: 12, bottom: 10, right: 12))
|
|
}
|
|
snp.makeConstraints { make in make.height.equalTo(44) }
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
|
|
/// 带边框的多行输入框。
|
|
final class TaskBorderTextView: UIView {
|
|
|
|
let textView = UITextView()
|
|
|
|
init(placeholder: String) {
|
|
super.init(frame: .zero)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = AppRadius.sm
|
|
layer.borderWidth = 1
|
|
layer.borderColor = AppColor.border.cgColor
|
|
|
|
textView.font = .app(.body)
|
|
textView.textColor = AppColor.textPrimary
|
|
textView.text = placeholder
|
|
textView.textColor = AppColor.textTertiary
|
|
addSubview(textView)
|
|
textView.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview().inset(AppSpacing.xs)
|
|
}
|
|
snp.makeConstraints { make in make.height.equalTo(80) }
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|