Visual_Novel_iOS/crush/Crush/Src/Components/UI/Placeholder/PlaceholderView.swift

169 lines
4.9 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// PlaceholderView.swift
// Crush
//
// Created by Leon on 2025/7/14.
//
import SnapKit
import UIKit
/// A reusable placeholder view with an image and text label
class PlaceholderView: UIView {
// MARK: - Properties
lazy var emptyImage: UIImage? = {
UIImage(named: "empty_placeholder_icon")
}()
var viewStartOffset: CGFloat = 0
var startY: CGFloat = 0
private let placeholderImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.tintColor = .gray // Adjust tint for template images
return imageView
}()
private let placeholderLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.textColor = .gray
label.font = .systemFont(ofSize: 16, weight: .regular)
label.numberOfLines = 0 // Allow multiple lines
return label
}()
// MARK: - Initialization
init(text: String, viewStartOffset: CGFloat = 0) {
super.init(frame: .zero)
self.viewStartOffset = viewStartOffset
setupViews(image: emptyImage)
updateViewOffset(text: text)
}
init(text: String, startY: CGFloat = 0) {
super.init(frame: .zero)
self.startY = startY
setupViews(image: emptyImage)
updateViewStartY(text: text)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
private func setupViews(image: UIImage?) {
isUserInteractionEnabled = false
backgroundColor = .clear // Adjust as needed
// Add subviews
addSubview(placeholderImageView)
addSubview(placeholderLabel)
// Configure content
placeholderImageView.image = image
}
// MARK: - Public Methods
func updateViewOffset(text: String) {
placeholderLabel.text = text
placeholderImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset((-40 + viewStartOffset) * 0.5) // Offset to position image above text
make.size.equalTo(CGSize(width: 183, height: 135))
}
placeholderLabel.snp.makeConstraints { make in
make.top.equalTo(placeholderImageView.snp.bottom).offset(16)
make.left.right.equalToSuperview().inset(16)
}
}
func updateViewStartY(text: String) {
placeholderLabel.text = text
placeholderImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(startY)
make.width.height.equalTo(100) // Adjust size as needed
}
placeholderLabel.snp.makeConstraints { make in
make.top.equalTo(placeholderImageView.snp.bottom).offset(16)
make.left.right.equalToSuperview().inset(16)
}
}
}
// MARK: - UIView Extension
extension UIView {
/// Adds a placeholder view with an image and text to the view
/// - Parameters:
/// - text: The placeholder text
/// - Returns: The created PlaceholderView instance
@discardableResult
func showEmpty(text: String, viewStartOffset: CGFloat = 0) -> PlaceholderView {
// Remove any existing placeholder views
subviews.filter { $0 is PlaceholderView }.forEach { $0.removeFromSuperview() }
// Create and configure placeholder view
let placeholderView = PlaceholderView(text: text, viewStartOffset: viewStartOffset)
addSubview(placeholderView)
// Setup Auto Layout
placeholderView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
placeholderView.setNeedsDisplay()
placeholderView.layoutIfNeeded()
return placeholderView
}
@discardableResult
func showStartYEmpty(text: String, startY: CGFloat = 200) -> PlaceholderView {
// Remove any existing placeholder views
subviews.filter { $0 is PlaceholderView }.forEach { $0.removeFromSuperview() }
// Create and configure placeholder view
let placeholderView = PlaceholderView(text: text, startY: startY)
addSubview(placeholderView)
// Setup Auto Layout
placeholderView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
return placeholderView
}
/// Removes any existing placeholder view
func removeEmpty() {
subviews.filter { $0 is PlaceholderView }.forEach { $0.removeFromSuperview() }
}
func hideEmpty(){
removeEmpty()
}
// MARK: - Public
func setupEmpty(empty: Bool, startY: CGFloat? = 0, msg: String?){
if(empty){
if let y = startY, y > 0{
showStartYEmpty(text: msg ?? "", startY: y)
}else{
showEmpty(text: msg ?? "")
}
}else{
removeEmpty()
}
}
}