diff --git a/suixinkan/UI/TravelAlbum/TravelAlbumDetailViewController.swift b/suixinkan/UI/TravelAlbum/TravelAlbumDetailViewController.swift index f866d8f..7df228b 100644 --- a/suixinkan/UI/TravelAlbum/TravelAlbumDetailViewController.swift +++ b/suixinkan/UI/TravelAlbum/TravelAlbumDetailViewController.swift @@ -23,8 +23,10 @@ final class TravelAlbumDetailViewController: BaseViewController { private var collectionView: UICollectionView! private var dataSource: UICollectionViewDiffableDataSource! private let bottomBar = UIView() + private let bottomActionStack = UIStackView() private let deleteSelectedButton = UIButton(type: .system) private let uploadButton = UIButton(type: .system) + private var isDeleteSelectedButtonVisible = false init(albumId: Int, api: any TravelAlbumServing = NetworkServices.shared.travelAlbumAPI) { viewModel = TravelAlbumDetailViewModel(albumId: albumId) @@ -85,9 +87,12 @@ final class TravelAlbumDetailViewController: BaseViewController { } bottomBar.backgroundColor = AppColor.pageBackground + bottomActionStack.axis = .vertical + bottomActionStack.spacing = 8 configureBottomButton(deleteSelectedButton, title: "删除选中(0)", color: UIColor(hex: 0xE53935)) configureBottomButton(uploadButton, title: "上传照片", color: AppColor.primary) deleteSelectedButton.isHidden = true + deleteSelectedButton.alpha = 0 view.addSubview(scrollContainer) scrollContainer.addSubview(infoCard) @@ -99,24 +104,25 @@ final class TravelAlbumDetailViewController: BaseViewController { manageCard.addSubview(selectButton) manageCard.addSubview(collectionView) view.addSubview(bottomBar) - bottomBar.addSubview(deleteSelectedButton) - bottomBar.addSubview(uploadButton) + bottomBar.addSubview(bottomActionStack) + bottomActionStack.addArrangedSubview(deleteSelectedButton) + bottomActionStack.addArrangedSubview(uploadButton) } override func setupConstraints() { bottomBar.snp.makeConstraints { make in make.leading.trailing.bottom.equalToSuperview() } - deleteSelectedButton.snp.makeConstraints { make in + bottomActionStack.snp.makeConstraints { make in make.top.equalToSuperview().offset(12) make.leading.trailing.equalToSuperview().inset(20) - make.height.equalTo(48) + make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12) + } + deleteSelectedButton.snp.makeConstraints { make in + make.height.equalTo(48).priority(.high) } uploadButton.snp.makeConstraints { make in - make.top.equalTo(deleteSelectedButton.snp.bottom).offset(8) - make.leading.trailing.equalTo(deleteSelectedButton) - make.height.equalTo(48) - make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12) + make.height.equalTo(48).priority(.high) } scrollContainer.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).offset(12) @@ -189,12 +195,15 @@ final class TravelAlbumDetailViewController: BaseViewController { selectButton.isHidden = viewModel.selectedTab != .all selectButton.setImage(UIImage(systemName: viewModel.isSelectionMode ? "checkmark.circle.fill" : "circle"), for: .normal) selectButton.tintColor = viewModel.isSelectionMode ? AppColor.primary : AppColor.textTertiary - deleteSelectedButton.isHidden = !(viewModel.isSelectionMode && !viewModel.selectedMaterialIds.isEmpty) deleteSelectedButton.setTitle("删除选中(\(viewModel.selectedMaterialIds.count))", for: .normal) + setDeleteSelectedButtonVisible(viewModel.isSelectionMode && !viewModel.selectedMaterialIds.isEmpty) var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([0]) snapshot.appendItems(viewModel.materials) + if !snapshot.itemIdentifiers.isEmpty { + snapshot.reconfigureItems(snapshot.itemIdentifiers) + } dataSource.apply(snapshot, animatingDifferences: true) if viewModel.isLoading && viewModel.album == nil { @@ -231,6 +240,29 @@ final class TravelAlbumDetailViewController: BaseViewController { button.layer.cornerRadius = 10 } + private func setDeleteSelectedButtonVisible(_ visible: Bool) { + guard visible != isDeleteSelectedButtonVisible else { return } + isDeleteSelectedButtonVisible = visible + + let changes = { + self.deleteSelectedButton.isHidden = !visible + self.deleteSelectedButton.alpha = visible ? 1 : 0 + self.view.layoutIfNeeded() + } + guard view.window != nil else { + changes() + return + } + + view.layoutIfNeeded() + UIView.animate( + withDuration: 0.25, + delay: 0, + options: [.curveEaseInOut, .beginFromCurrentState], + animations: changes + ) + } + private func makeLayout() -> UICollectionViewCompositionalLayout { UICollectionViewCompositionalLayout { _, environment in let spacing: CGFloat = 8 diff --git a/suixinkan/UI/TravelAlbum/TravelAlbumEntryViewController.swift b/suixinkan/UI/TravelAlbum/TravelAlbumEntryViewController.swift index bd69ef8..24f43ba 100644 --- a/suixinkan/UI/TravelAlbum/TravelAlbumEntryViewController.swift +++ b/suixinkan/UI/TravelAlbum/TravelAlbumEntryViewController.swift @@ -42,7 +42,7 @@ final class TravelAlbumEntryViewController: BaseViewController { tableView.backgroundColor = .white tableView.separatorStyle = .none tableView.rowHeight = UITableView.automaticDimension - tableView.estimatedRowHeight = 132 + tableView.estimatedRowHeight = 148 tableView.delegate = self tableView.register(TravelAlbumTaskCell.self, forCellReuseIdentifier: TravelAlbumTaskCell.reuseIdentifier) @@ -305,10 +305,14 @@ private final class TravelAlbumTaskCell: UITableViewCell { nameLabel.font = .systemFont(ofSize: 16, weight: .bold) nameLabel.textColor = AppColor.textPrimary + nameLabel.numberOfLines = 1 timeLabel.font = .systemFont(ofSize: 12) timeLabel.textColor = AppColor.textTertiary + timeLabel.numberOfLines = 1 phoneLabel.font = .systemFont(ofSize: 12) phoneLabel.textColor = AppColor.textTertiary + phoneLabel.numberOfLines = 1 + phoneLabel.setContentCompressionResistancePriority(.required, for: .vertical) shareButton.setImage(UIImage(systemName: "square.and.arrow.up"), for: .normal) shareButton.tintColor = AppColor.primary @@ -336,8 +340,8 @@ private final class TravelAlbumTaskCell: UITableViewCell { make.edges.equalToSuperview().inset(UIEdgeInsets(top: 6, left: 20, bottom: 6, right: 20)) } coverView.snp.makeConstraints { make in - make.leading.top.bottom.equalToSuperview().inset(10) - make.size.equalTo(86) + make.leading.top.bottom.equalToSuperview().inset(12) + make.size.equalTo(112) } iconView.snp.makeConstraints { make in make.center.equalToSuperview() @@ -360,16 +364,18 @@ private final class TravelAlbumTaskCell: UITableViewCell { } timeLabel.snp.makeConstraints { make in make.top.equalTo(nameLabel.snp.bottom).offset(7) - make.leading.trailing.equalTo(nameLabel) + make.leading.equalTo(nameLabel) + make.trailing.equalToSuperview().offset(-12) } phoneLabel.snp.makeConstraints { make in make.top.equalTo(timeLabel.snp.bottom).offset(5) - make.leading.trailing.equalTo(nameLabel) + make.leading.equalTo(nameLabel) + make.trailing.equalToSuperview().offset(-12) } uploadButton.snp.makeConstraints { make in make.top.equalTo(phoneLabel.snp.bottom).offset(9) make.trailing.equalToSuperview().offset(-10) - make.bottom.equalToSuperview().offset(-10) + make.bottom.equalToSuperview().offset(-12) make.height.equalTo(34) make.width.greaterThanOrEqualTo(104) }