Commit 36283345 authored by CZ1004's avatar CZ1004

【优化】时间选择器

parent 545b78fb
......@@ -316,17 +316,19 @@ class PhotoRemoveViewController: BaseViewController {
func showTrashView(){
DispatchQueue.main.async {
self.trashSubView.isHidden = false
UIView.animate(withDuration: 0.1) {
UIView.animate(withDuration: 0.2) {
// 更新约束
self.bottomConstraint?.update(offset: 0)
self.view.layoutIfNeeded()
}
}
}
func hideTrashView(){
DispatchQueue.main.async {
UIView.animate(withDuration: 0.1) {
UIView.animate(withDuration: 0.2) {
// 更新约束
self.bottomConstraint?.update(offset: 78 + safeHeight)
self.view.layoutIfNeeded()
}completion: { finished in
self.trashSubView.isHidden = true
}
......@@ -431,9 +433,13 @@ class PhotoRemoveViewController: BaseViewController {
func saveDataToKeepListDB(){
if let type = self.mediaType{
if let dataSg = Singleton.shared.keepList[type]{
var uinqueId = UUID().uuidString
for item in dataSg{
// 如果是视频的话不会进行分组,所以每次传入不同的id组
let uinqueId = UUID().uuidString
if type == .video {
// 如果是视频的话不会进行分组,所以每次传入不同的id
// 重新生成一个
uinqueId = UUID().uuidString
}
let success = GroupDatabase.shared.insert(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: type == TrashTypeEnum.video ? 2 : 1,groupId: uinqueId)
if success == false {
Print("保留单利数据到数据库保留列表失败")
......
......@@ -11,7 +11,7 @@ class DateSelectButtonView : UIView {
var closeCallBack : ()->Void = {}
var type : PikerDateType?
var type : PickerDateType?
lazy var dateButton : UIButton = {
let button = UIButton(type: .custom)
......
......@@ -21,15 +21,19 @@ class PhotosRemoveBaseView: UIView {
func reload(index:Int) -> Void {
if let url = url {
self.innerVideoController = VideoViewController()
if let vc = self.innerVideoController {
vc.isAutoPlay = index == 0
vc.url = url
self.imageView.removeFromSuperview()
self.addSubview(vc.view)
vc.view.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview()
if self.innerVideoController == nil {
self.innerVideoController = VideoViewController()
if let vc = self.innerVideoController {
vc.isAutoPlay = index == 0
vc.url = url
self.imageView.removeFromSuperview()
self.addSubview(vc.view)
vc.view.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview()
}
}
}else {
self.innerVideoController?.playerViewController.player?.play()
}
}
}
......@@ -72,7 +76,11 @@ class PhotosRemoveBaseView: UIView {
addSubview(imageView)
leftButton.frame = CGRect(x: 0, y: 0, width: 95, height: 42)
leftButton.center = imageView.center
if self.url != nil {
self.leftButton.center = self.innerVideoController?.view.center ?? imageView.center
}else {
self.leftButton.center = imageView.center
}
leftButton.setTitle("Delete", for: .normal)
leftButton.backgroundColor = UIColor(red: 0.95, green: 0.21, blue: 0.21, alpha: 1)
leftButton.tintColor = .white
......@@ -83,7 +91,11 @@ class PhotosRemoveBaseView: UIView {
rightButton.frame = CGRect(x: 0, y: 0, width: 95, height: 42)
rightButton.center = imageView.center
if self.url != nil {
self.rightButton.center = self.innerVideoController?.view.center ?? imageView.center
}else {
self.rightButton.center = imageView.center
}
rightButton.setTitle("Retain", for: .normal)
rightButton.backgroundColor = UIColor(red: 0.18, green: 0.76, blue: 0.35, alpha: 1)
rightButton.tintColor = .white
......@@ -101,17 +113,24 @@ class PhotosRemoveBaseView: UIView {
}
func showLeftButton() {
self.leftButton.center = imageView.center
UIView.animate(withDuration: 0.2) {
self.leftButton.alpha = 1
self.maskTempleteView.backgroundColor = UIColor(red: 0.95, green: 0.21, blue: 0.21, alpha: 0.4000)
self.addSubview(self.maskTempleteView)
self.rightButton.alpha = 0
if self.url != nil {
self.leftButton.center = self.innerVideoController?.view.center ?? imageView.center
}else {
self.leftButton.center = imageView.center
}
self.leftButton.alpha = 1
self.rightButton.alpha = 0
self.maskTempleteView.backgroundColor = UIColor(red: 0.95, green: 0.21, blue: 0.21, alpha: 0.4000)
self.addSubview(self.maskTempleteView)
}
func showRightButton() {
self.rightButton.center = imageView.center
if self.url != nil {
self.rightButton.center = self.innerVideoController?.view.center ?? imageView.center
}else {
self.rightButton.center = imageView.center
}
UIView.animate(withDuration: 0.2) {
self.rightButton.alpha = 1
self.maskTempleteView.backgroundColor = UIColor(red: 0.26, green: 0.78, blue: 0.41, alpha: 0.4000)
......@@ -121,12 +140,18 @@ class PhotosRemoveBaseView: UIView {
}
func hideButtons() {
UIView.animate(withDuration: 0.2) { [self] in
self.leftButton.alpha = 0
self.rightButton.alpha = 0
self.maskTempleteView.removeFromSuperview()
self.leftButton.center = self.imageView.center
self.rightButton.center = self.imageView.center
if self.url != nil {
self.rightButton.center = self.innerVideoController?.view.center ?? imageView.center
self.leftButton.center = self.innerVideoController?.view.center ?? imageView.center
}else {
self.leftButton.center = self.imageView.center
self.rightButton.center = self.imageView.center
}
}
}
......
......@@ -127,8 +127,8 @@ class ResourceFilterBoxView : UIView {
private func setDefaultDataInPage(){
// 设置按钮
resetByType(date: self.startDate, type: PikerDateType.start)
resetByType(date: self.endDate, type: PikerDateType.end)
resetByType(date: self.startDate, type: PickerDateType.start)
resetByType(date: self.endDate, type: PickerDateType.end)
// 设置选择框
DispatchQueue.main.async {
......@@ -141,7 +141,7 @@ class ResourceFilterBoxView : UIView {
/// - Parameters:
/// - date: 时间
/// - type: 类型
private func resetByType(date:Date?,type:PikerDateType){
private func resetByType(date:Date?,type:PickerDateType){
if let date = date {
let timeNumber = getYearAndMonthFromDate(currentDate: date)
if let year = timeNumber.0{
......@@ -167,13 +167,14 @@ class ResourceFilterBoxView : UIView {
/// - year: 年
/// - month: 月
/// - type: 按钮类型
func resetDateStringFromYearAndMonth(year: Int, month: Int ,type: PikerDateType){
func resetDateStringFromYearAndMonth(year: Int, month: Int ,type: PickerDateType){
DispatchQueue.main.async {
if type == .start {
self.startDateButton.dateButton.setTitle("From \(self.getMonthEn(month: month)) \(year)", for: .normal)
self.startDateButton.closeButton.isHidden = false
self.startDate = self.dateFrom(year: year, month: month)
}else {
// 判断结束时间是否大于开始时间,如果是
self.endDateButton.dateButton.setTitle("To \(self.getMonthEn(month: month)) \(year)", for: .normal)
self.endDateButton.closeButton.isHidden = false
self.endDate = self.lastDayOfMonth(year: year, month: month)
......@@ -214,9 +215,13 @@ class ResourceFilterBoxView : UIView {
self.startDateButton.closeCallBack = {
self.startDate = nil
self.datePicker?.startDate = nil
self.datePicker?.reloadData()
}
self.endDateButton.closeCallBack = {
self.endDate = nil
self.datePicker?.endDate = nil
self.datePicker?.reloadData()
}
self.startDateButton.reSetButtonTitle()
......@@ -348,18 +353,24 @@ class ResourceFilterBoxView : UIView {
popDatePikerView(type: .end)
}
func popDatePikerView(type: PikerDateType){
showDatePicker(type: type)
func popDatePikerView(type: PickerDateType){
showDatePicker(type: type,startDate: self.startDate,endDate: self.endDate)
}
// 显示
func showDatePicker(type: PikerDateType){
func showDatePicker(type: PickerDateType,startDate:Date?,endDate:Date?){
if self.datePicker != nil {
self.datePicker?.type = type
self.datePicker?.startDate = self.startDate
self.datePicker?.endDate = self.endDate
self.datePicker?.reloadData()
return
}
self.datePicker = YearMonthPickerView()
self.datePicker?.type = type
self.datePicker?.startDate = self.startDate
self.datePicker?.endDate = self.endDate
self.datePicker?.backgroundColor = .white
if let window = cWindow,let datePicker = self.datePicker {
let datePickerFrame = CGRect(x: 0, y: window.height, width:window.width, height: 204)
......
......@@ -5,26 +5,38 @@
// Created by edy on 2025/5/12.
//
import Foundation
import UIKit
enum PikerDateType {
enum PickerDateType {
case start
case end
}
class YearMonthPickerView: UIView {
var type : PikerDateType = .start
var type: PickerDateType = .start {
didSet {
reloadData()
}
}
// MARK: - Properties
private var selectedYear: Int = 0
private var selectedMonth: Int = 0
private let calendar = Calendar.current
private var currentYear: Int
private var currentMonth: Int
var startDate: Date? {
didSet { reloadData() }
}
var endDate: Date? {
didSet { reloadData() }
}
var onCancel: (() -> Void)?
var onConfirm: ((_ type : PikerDateType,_ year: Int, _ month: Int) -> Void)?
var onConfirm: ((_ type: PickerDateType, _ year: Int, _ month: Int) -> Void)?
private let pickerView: UIPickerView = {
let picker = UIPickerView()
......@@ -32,106 +44,136 @@ class YearMonthPickerView: UIView {
return picker
}()
private let years = Array(Array(1970...Calendar.current.component(.year, from: Date())).reversed())
private lazy var years: [Int] = {
Array(1970...currentYear).reversed()
}()
private lazy var months: [String] = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US")
return formatter.monthSymbols
DateFormatter().monthSymbols ?? []
}()
// MARK: - Initialization
override init(frame: CGRect) {
currentYear = calendar.component(.year, from: Date())
currentMonth = calendar.component(.month, from: Date())
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
currentYear = calendar.component(.year, from: Date())
currentMonth = calendar.component(.month, from: Date())
super.init(coder: coder)
setupView()
}
// MARK: - Public Methods
func reloadData() {
configureInitialSelection()
pickerView.reloadAllComponents()
}
// MARK: - Setup
private func setupView() {
backgroundColor = .white
layer.cornerRadius = 12
layer.masksToBounds = true
// 按钮容器
let buttonContainer = UIView()
buttonContainer.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)
buttonContainer.translatesAutoresizingMaskIntoConstraints = false
let buttonContainer = createButtonContainer()
let stackView = UIStackView(arrangedSubviews: [buttonContainer, pickerView])
stackView.axis = .vertical
stackView.spacing = 0
stackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
pickerView.delegate = self
pickerView.dataSource = self
configureInitialSelection()
}
private func createButtonContainer() -> UIView {
let container = UIView()
container.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)
container.translatesAutoresizingMaskIntoConstraints = false
container.heightAnchor.constraint(equalToConstant: 42).isActive = true
// 取消按钮
let cancelButton = UIButton(type: .system)
cancelButton.setTitle("Cancel", for: .normal)
cancelButton.contentHorizontalAlignment = .left
cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
cancelButton.translatesAutoresizingMaskIntoConstraints = false
cancelButton.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
cancelButton.setTitleColor(UIColor(red: 0.6, green: 0.6, blue: 0.6, alpha: 1), for: .normal)
cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
cancelButton.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
// 确认按钮
let confirmButton = UIButton(type: .system)
confirmButton.setTitle("Completed", for: .normal)
confirmButton.contentHorizontalAlignment = .right
confirmButton.addTarget(self, action: #selector(confirmAction), for: .touchUpInside)
confirmButton.translatesAutoresizingMaskIntoConstraints = false
cancelButton.setTitleColor(UIColor(red: 0.07, green: 0.07, blue: 0.07, alpha: 1), for: .normal)
cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
confirmButton.addTarget(self, action: #selector(confirmAction), for: .touchUpInside)
confirmButton.setTitleColor(UIColor(red: 0.07, green: 0.07, blue: 0.07, alpha: 1), for: .normal)
confirmButton.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
buttonContainer.addSubview(cancelButton)
buttonContainer.addSubview(confirmButton)
[cancelButton, confirmButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
container.addSubview($0)
}
// 按钮容器约束
NSLayoutConstraint.activate([
buttonContainer.heightAnchor.constraint(equalToConstant: 42),
cancelButton.leadingAnchor.constraint(equalTo: buttonContainer.leadingAnchor, constant: 16),
cancelButton.centerYAnchor.constraint(equalTo: buttonContainer.centerYAnchor),
cancelButton.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
cancelButton.centerYAnchor.constraint(equalTo: container.centerYAnchor),
confirmButton.trailingAnchor.constraint(equalTo: buttonContainer.trailingAnchor, constant: -16),
confirmButton.centerYAnchor.constraint(equalTo: buttonContainer.centerYAnchor)
confirmButton.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
confirmButton.centerYAnchor.constraint(equalTo: container.centerYAnchor)
])
// 主布局
let stackView = UIStackView(arrangedSubviews: [buttonContainer, pickerView])
stackView.axis = .vertical
stackView.spacing = 0
stackView.translatesAutoresizingMaskIntoConstraints = false
return container
}
private func configureInitialSelection() {
let targetDate: Date?
switch type {
case .start: targetDate = startDate
case .end: targetDate = endDate
}
addSubview(stackView)
let date = targetDate ?? Date()
var year = calendar.component(.year, from: date)
var month = calendar.component(.month, from: date)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
// 应用约束条件
(year, month) = applyConstraints(to: year, month: month)
pickerView.delegate = self
pickerView.dataSource = self
// 设置初始选择
let currentYear = Calendar.current.component(.year, from: Date())
let currentMonth = Calendar.current.component(.month, from: Date())
selectedYear = currentYear
selectedMonth = currentMonth - 1
// 自动滚动到有效位置
scrollToValidYear(year, month: month)
}
private func scrollToValidYear(_ year: Int, month: Int) {
guard let yearIndex = years.firstIndex(of: year) else { return }
selectedYear = year
selectedMonth = month - 1
if let yearIndex = years.firstIndex(of: currentYear) {
pickerView.selectRow(yearIndex, inComponent: 1, animated: false)
}
pickerView.tintColor = .red
pickerView.selectRow(currentMonth - 1, inComponent: 0, animated: false)
pickerView.selectRow(yearIndex, inComponent: 1, animated: false)
pickerView.selectRow(selectedMonth, inComponent: 0, animated: false)
}
// MARK: - 按钮操作
// MARK: - Button Actions
@objc private func cancelAction() {
onCancel?()
}
@objc private func confirmAction() {
onConfirm?(self.type,selectedYear, selectedMonth + 1)
// 最终校验
let (validYear, validMonth) = applyConstraints(to: selectedYear, month: selectedMonth + 1)
scrollToValidYear(validYear, month: validMonth)
onConfirm?(type, validYear, validMonth)
}
}
......@@ -142,32 +184,124 @@ extension YearMonthPickerView: UIPickerViewDataSource, UIPickerViewDelegate {
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return component == 0 ? months.count : years.count
component == 0 ? 12 : years.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return component == 0 ? months[row] : "\(years[row])"
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let label = UILabel()
label.textAlignment = .center
let year = component == 1 ? years[row] : selectedYear
let month = component == 0 ? (row + 1) : (selectedMonth + 1)
if component == 0 {
label.text = months[row]
} else {
label.text = "\(years[row])"
}
label.textColor = isDateValid(year: year, month: month) ? .black : .lightGray
return label
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
selectedMonth = row
} else {
if component == 1 {
selectedYear = years[row]
adjustMonthSelection()
} else {
selectedMonth = row
}
// 自动修正无效选择
if !isDateValid(year: selectedYear, month: selectedMonth + 1) {
let (validYear, validMonth) = applyConstraints(to: selectedYear, month: selectedMonth + 1)
scrollToValidYear(validYear, month: validMonth)
}
}
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
return component == 0 ? self.width/2 : self.width/2
bounds.width / 2
}
}
// MARK: - Date Validation
extension YearMonthPickerView {
private func isDateValid(year: Int, month: Int) -> Bool {
// 检查当前时间限制
if year > currentYear || (year == currentYear && month > currentMonth) {
return false
}
// 检查开始/结束时间约束
switch type {
case .start:
if let endDate = endDate {
let endYear = calendar.component(.year, from: endDate)
let endMonth = calendar.component(.month, from: endDate)
return (year < endYear) || (year == endYear && month <= endMonth)
}
case .end:
if let startDate = startDate {
let startYear = calendar.component(.year, from: startDate)
let startMonth = calendar.component(.month, from: startDate)
return (year > startYear) || (year == startYear && month >= startMonth)
}
}
return true
}
private var currentYear: Int {
return Calendar.current.component(.year, from: Date())
private func applyConstraints(to year: Int, month: Int) -> (year: Int, month: Int) {
var validYear = year
var validMonth = month
// 当前时间约束
validYear = min(validYear, currentYear)
validMonth = min(validMonth, validYear == currentYear ? currentMonth : 12)
// 开始/结束时间约束
switch type {
case .start:
if let endDate = endDate {
let endYear = calendar.component(.year, from: endDate)
let endMonth = calendar.component(.month, from: endDate)
validYear = min(validYear, endYear)
validMonth = min(validMonth, validYear == endYear ? endMonth : 12)
}
case .end:
if let startDate = startDate {
let startYear = calendar.component(.year, from: startDate)
let startMonth = calendar.component(.month, from: startDate)
validYear = max(validYear, startYear)
validMonth = max(validMonth, validYear == startYear ? startMonth : 1)
}
}
return (validYear, validMonth)
}
private var currentMonth: Int {
return Calendar.current.component(.month, from: Date())
private func adjustMonthSelection() {
let maxMonth: Int
if selectedYear == currentYear {
maxMonth = currentMonth
} else if let constraintMonth = getConstraintMonth() {
maxMonth = (type == .start) ? constraintMonth : 12
} else {
maxMonth = 12
}
if (selectedMonth + 1) > maxMonth {
selectedMonth = maxMonth - 1
pickerView.selectRow(selectedMonth, inComponent: 0, animated: true)
}
}
private func getConstraintMonth() -> Int? {
switch type {
case .start:
return endDate.flatMap { calendar.component(.month, from: $0) }
case .end:
return startDate.flatMap { calendar.component(.month, from: $0) }
}
}
}
......@@ -268,6 +268,8 @@ extension HomeInfoTableViewCell:UICollectionViewDelegate,UICollectionViewDataSou
let vc = PMShowImgVideoController()
if model?.type == .SimilarVideos || model?.type == .videos {
vc.state = .similarVideos
}else if model?.type == .duplicates {
vc.state = .duplicates
}else{
vc.state = .similarPhotos
}
......
......@@ -16,6 +16,8 @@ class PMShowImgVideoController: BaseViewController {
case similarPhotos
// 相似视频
case similarVideos
// 重复项
case duplicates
}
// 资源类型 0-图片 1-视频
......@@ -290,11 +292,9 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
showName.loadPhotoOrVideo { durs, icon in
cell.icon = icon
}
if let data = self.homeDataSource {
cell.bestResultButton.isHidden = indexPath.row != 0 || data.count <= 1
}else{
cell.bestResultButton.isHidden = true
if self.homeDataSource == nil {
cell.selectBtn.isHidden = true
cell.bestResultButton.isHidden = true
}
cell.isCurrent = selectSet.contains(indexPath.row)
cell.callblock = {[weak self] in
......@@ -334,9 +334,7 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
}
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
if let data = self.homeDataSource {
}else{
if self.homeDataSource == nil {
cell.selectBtn.isHidden = true
}
showName.loadPhotoOrVideo { duration, icon in
......@@ -349,14 +347,14 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
}
}
if state == .similarPhotos {
if state == .similarPhotos || state == .duplicates {
if collectionView == MaxCollection {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isCurrent = selectSet.contains(indexPath.row)
if let data = self.homeDataSource {
cell.bestResultButton.isHidden = indexPath.row != 0 || data.count <= 1
cell.bestResultButton.isHidden = indexPath.row != 0 || data.count <= 1 || state == .duplicates
}
cell.callblock = {[weak self] in
guard let self = self else { return }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment