chat setting font size
This commit is contained in:
parent
4c4c578d0b
commit
1cedc98838
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
// font
|
||||
struct FontRow: RowModel {
|
||||
|
|
@ -13,57 +14,129 @@ struct FontRow: RowModel {
|
|||
let icon: String
|
||||
let title: String
|
||||
var cellReuseID: String { "ChatFontCell" }
|
||||
func cellHeight(tableWidth: CGFloat) -> CGFloat { 50 }
|
||||
func cellHeight(tableWidth: CGFloat) -> CGFloat { 80 }
|
||||
}
|
||||
|
||||
class ChatFontCell: ChatSettingBaseCell, CellConfigurable {
|
||||
|
||||
private var currentFontSize: Int = 20
|
||||
private let minFontSize: Int = 10
|
||||
private let maxFontSize: Int = 30
|
||||
|
||||
lazy var iconImgView: UIImageView = {
|
||||
let imgView = UIImageView(image: UIImage(named: "role_exchange_mode"))
|
||||
let imgView = UIImageView(image: UIImage(named: "role_font"))
|
||||
return imgView
|
||||
}()
|
||||
|
||||
lazy var titleLab: UILabel = {
|
||||
let lab = UILabel()
|
||||
lab.text = "XL-0826-32K"
|
||||
lab.font = UIFont.boldSystemFont(ofSize: 14)
|
||||
lab.text = "Font size"
|
||||
lab.font = UIFont.systemFont(ofSize: 14)
|
||||
lab.textColor = UIColor(hex: "#666666")
|
||||
return lab
|
||||
}()
|
||||
|
||||
lazy var fontSub: UIButton = {
|
||||
let btn = UIButton()
|
||||
btn.setImage(UIImage(named: "role_setting_font_sub"), for: .normal)
|
||||
btn.addTarget(self, action: #selector(fontSubTap), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
|
||||
lazy var fontAdd: UIButton = {
|
||||
let btn = UIButton()
|
||||
btn.setImage(UIImage(named: "role_setting_font_add"), for: .normal)
|
||||
btn.addTarget(self, action: #selector(fontAddTap), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
|
||||
lazy var fontLab: UILabel = {
|
||||
lazy var fontSizeLab: UILabel = {
|
||||
let lab = UILabel()
|
||||
lab.text = "20"
|
||||
lab.font = UIFont.systemFont(ofSize: 14)
|
||||
lab.textColor = UIColor(hex: "#999999")
|
||||
lab.textAlignment = .center
|
||||
lab.textAlignment = .right
|
||||
return lab
|
||||
}()
|
||||
|
||||
lazy var sliderContainer: UIView = {
|
||||
let view = UIView()
|
||||
return view
|
||||
}()
|
||||
|
||||
lazy var minusButton: UIButton = {
|
||||
let btn = UIButton(type: .custom)
|
||||
// 优先使用图片,否则显示蓝色文字
|
||||
if let image = UIImage(named: "role_setting_font_sub") {
|
||||
btn.setImage(image, for: .normal)
|
||||
} else {
|
||||
btn.setTitle("A-", for: .normal)
|
||||
btn.setTitleColor(UIColor(hex: "#0066FF"), for: .normal)
|
||||
btn.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
||||
}
|
||||
btn.addTarget(self, action: #selector(decreaseFontSize), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
|
||||
lazy var plusButton: UIButton = {
|
||||
let btn = UIButton(type: .custom)
|
||||
// 优先使用图片,否则显示蓝色文字
|
||||
if let image = UIImage(named: "role_setting_font_add") {
|
||||
btn.setImage(image, for: .normal)
|
||||
} else {
|
||||
btn.setTitle("A+", for: .normal)
|
||||
btn.setTitleColor(UIColor(hex: "#0066FF"), for: .normal)
|
||||
btn.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
||||
}
|
||||
btn.addTarget(self, action: #selector(increaseFontSize), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
|
||||
lazy var slider: UISlider = {
|
||||
let slider = UISlider()
|
||||
slider.minimumValue = Float(minFontSize)
|
||||
slider.maximumValue = Float(maxFontSize)
|
||||
slider.value = Float(currentFontSize)
|
||||
|
||||
// 设置灰色 track(根据图片描述)
|
||||
slider.minimumTrackTintColor = UIColor(hex: "#E0E0E0")
|
||||
slider.maximumTrackTintColor = UIColor(hex: "#E0E0E0")
|
||||
|
||||
// 自定义白色圆形 thumb
|
||||
let thumbSize: CGFloat = 24
|
||||
UIGraphicsBeginImageContextWithOptions(CGSize(width: thumbSize, height: thumbSize), false, 0.0)
|
||||
if let context = UIGraphicsGetCurrentContext() {
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
context.fillEllipse(in: CGRect(x: 0, y: 0, width: thumbSize, height: thumbSize))
|
||||
// 添加阴影效果使thumb更突出
|
||||
context.setShadow(offset: CGSize(width: 0, height: 1), blur: 2, color: UIColor.black.withAlphaComponent(0.2).cgColor)
|
||||
}
|
||||
let thumbImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
slider.setThumbImage(thumbImage, for: .normal)
|
||||
slider.setThumbImage(thumbImage, for: .highlighted)
|
||||
|
||||
// 添加所有相关的事件监听,确保拖动流畅
|
||||
slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
|
||||
slider.addTarget(self, action: #selector(sliderTouchDown(_:)), for: .touchDown)
|
||||
slider.addTarget(self, action: #selector(sliderTouchUp(_:)), for: [.touchUpInside, .touchUpOutside])
|
||||
|
||||
return slider
|
||||
}()
|
||||
|
||||
private lazy var tickMarksContainer: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .clear
|
||||
return view
|
||||
}()
|
||||
|
||||
private var tickMarks: [UIView] = []
|
||||
|
||||
func configure(with row: RowModel) {
|
||||
guard let row = row as? FontRow else { return }
|
||||
titleLab.text = row.title
|
||||
iconImgView.image = UIImage(named: row.icon)
|
||||
|
||||
// 更新容器高度
|
||||
updateContainerHeight(80)
|
||||
|
||||
if let size = Int(row.count) {
|
||||
currentFontSize = max(minFontSize, min(maxFontSize, size))
|
||||
updateFontSize(currentFontSize, updateSlider: true)
|
||||
}
|
||||
}
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
configureViews()
|
||||
setupTickMarks()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
|
|
@ -71,48 +144,156 @@ class ChatFontCell: ChatSettingBaseCell, CellConfigurable {
|
|||
}
|
||||
|
||||
func configureViews() {
|
||||
|
||||
containerView.addSubview(iconImgView)
|
||||
containerView.addSubview(titleLab)
|
||||
containerView.addSubview(fontSub)
|
||||
containerView.addSubview(fontAdd)
|
||||
containerView.addSubview(fontLab)
|
||||
containerView.addSubview(fontSizeLab)
|
||||
containerView.addSubview(sliderContainer)
|
||||
|
||||
// 添加顺序很重要:先添加 slider,再添加 tick marks 覆盖在上面
|
||||
sliderContainer.addSubview(minusButton)
|
||||
sliderContainer.addSubview(plusButton)
|
||||
sliderContainer.addSubview(slider)
|
||||
sliderContainer.addSubview(tickMarksContainer)
|
||||
|
||||
// 确保 tick marks 在最上层,但不拦截触摸事件
|
||||
sliderContainer.bringSubviewToFront(tickMarksContainer)
|
||||
|
||||
iconImgView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(12)
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.width.height.equalTo(21)
|
||||
}
|
||||
|
||||
titleLab.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.centerY.equalTo(iconImgView)
|
||||
make.left.equalTo(iconImgView.snp.right).offset(9)
|
||||
make.right.equalTo(fontSub.snp.left).offset(-5)
|
||||
}
|
||||
|
||||
fontAdd.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
fontSizeLab.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(iconImgView)
|
||||
make.right.equalToSuperview().inset(20)
|
||||
make.width.height.equalTo(40)
|
||||
}
|
||||
|
||||
fontLab.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalTo(fontAdd.snp.left).offset(-10)
|
||||
sliderContainer.snp.makeConstraints { make in
|
||||
make.top.equalTo(iconImgView.snp.bottom).offset(12)
|
||||
make.left.right.equalToSuperview().inset(12)
|
||||
make.bottom.equalToSuperview().inset(12)
|
||||
make.height.equalTo(30)
|
||||
}
|
||||
|
||||
fontSub.snp.makeConstraints { make in
|
||||
minusButton.snp.makeConstraints { make in
|
||||
make.left.centerY.equalToSuperview()
|
||||
make.width.equalTo(30)
|
||||
}
|
||||
|
||||
plusButton.snp.makeConstraints { make in
|
||||
make.right.centerY.equalToSuperview()
|
||||
make.width.equalTo(30)
|
||||
}
|
||||
|
||||
slider.snp.makeConstraints { make in
|
||||
make.left.equalTo(minusButton.snp.right).offset(8)
|
||||
make.right.equalTo(plusButton.snp.left).offset(-8)
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalTo(fontLab.snp.left).offset(-10)
|
||||
make.width.height.equalTo(40)
|
||||
make.height.equalTo(30)
|
||||
}
|
||||
|
||||
// tick marks 覆盖在 slider 上,但允许触摸穿透到 slider
|
||||
tickMarksContainer.snp.makeConstraints { make in
|
||||
make.left.right.equalTo(slider)
|
||||
make.centerY.equalTo(slider)
|
||||
make.height.equalTo(slider).offset(4) // 稍微高一点以包含 tick marks
|
||||
}
|
||||
|
||||
// 确保 tick marks 不拦截触摸事件
|
||||
tickMarksContainer.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
private func setupTickMarks() {
|
||||
// 创建5个小点作为tick marks(均匀分布)
|
||||
let tickCount = 5
|
||||
for _ in 0..<tickCount {
|
||||
let tick = UIView()
|
||||
tick.backgroundColor = UIColor(hex: "#CCCCCC")
|
||||
tick.layer.cornerRadius = 2
|
||||
tick.isUserInteractionEnabled = false // 不拦截触摸
|
||||
tickMarksContainer.addSubview(tick)
|
||||
tickMarks.append(tick)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func fontSubTap() {
|
||||
print("sub sub sub")
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// 重新布局tick marks(在layout完成后)
|
||||
updateTickMarksLayout()
|
||||
}
|
||||
|
||||
@objc func fontAddTap() {
|
||||
print("add add add")
|
||||
private func updateTickMarksLayout() {
|
||||
guard tickMarks.count == 5, tickMarksContainer.bounds.width > 0 else { return }
|
||||
let totalWidth = tickMarksContainer.bounds.width
|
||||
// 5个点,4个间隔,均匀分布
|
||||
let spacing = totalWidth / 4.0
|
||||
let tickSize: CGFloat = 4
|
||||
let centerY = tickMarksContainer.bounds.height / 2.0
|
||||
|
||||
for (index, tick) in tickMarks.enumerated() {
|
||||
let centerX = CGFloat(index) * spacing
|
||||
tick.frame = CGRect(
|
||||
x: centerX - tickSize / 2.0,
|
||||
y: centerY - tickSize / 2.0,
|
||||
width: tickSize,
|
||||
height: tickSize
|
||||
)
|
||||
tick.layer.cornerRadius = tickSize / 2.0
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func decreaseFontSize() {
|
||||
if currentFontSize > minFontSize {
|
||||
currentFontSize -= 1
|
||||
updateFontSize(currentFontSize, updateSlider: true)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func increaseFontSize() {
|
||||
if currentFontSize < maxFontSize {
|
||||
currentFontSize += 1
|
||||
updateFontSize(currentFontSize, updateSlider: true)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func sliderValueChanged(_ slider: UISlider) {
|
||||
// 连续拖动时实时更新
|
||||
let newValue = Int(round(slider.value))
|
||||
if newValue != currentFontSize {
|
||||
currentFontSize = newValue
|
||||
updateFontSize(currentFontSize, updateSlider: false) // 不更新slider避免循环
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func sliderTouchDown(_ slider: UISlider) {
|
||||
// 开始拖动
|
||||
}
|
||||
|
||||
@objc private func sliderTouchUp(_ slider: UISlider) {
|
||||
// 结束拖动,确保值对齐到整数
|
||||
let newValue = Int(round(slider.value))
|
||||
currentFontSize = newValue
|
||||
updateFontSize(currentFontSize, updateSlider: true)
|
||||
}
|
||||
|
||||
private func updateFontSize(_ size: Int, updateSlider: Bool = true) {
|
||||
fontSizeLab.text = "\(size)"
|
||||
|
||||
if updateSlider {
|
||||
slider.setValue(Float(size), animated: false)
|
||||
}
|
||||
|
||||
// 更新按钮状态(可选:根据需求决定是否禁用)
|
||||
// minusButton.isEnabled = size > minFontSize
|
||||
// plusButton.isEnabled = size < maxFontSize
|
||||
|
||||
// 这里可以添加字体大小改变的回调
|
||||
// delegate?.fontSizeChanged(to: size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue