底部输入框:常用于文章的评论,分享,点赞。造一个通用的组件能帮助开发使用。
入坑点:
一开始根据设计稿8种类型设置了枚举,通过关联值来传递参数,在viewdidload
中switch type来动态添加子视图,根据初始化方法中是否带文本来添加按钮旁的文本,整个布局视图代码臃肿、繁琐重复,代码质量是十分差可重用性也差。
改善思路:
同事推荐官方navigationItem.leftBarButtonItems
的思路来写,根据传入的item数组来动态创建。限制左右item的数量,根据item一次创建视图然后更新布局。
//
// BottomInputBoxView.swift
// QDReaderHelper
//
// Created by wuxueqian on 2020/7/29.
import UIKit
import SnapKit
class BottomInputBoxView: UIView {
//MARK: - 公有属性
public var leftButtonItems: [BottomButtonItem]? {
didSet {
setupLeftItems()
updateCommentTriggerViewFrame()
}
}
public var rightButtonItems: [BottomButtonItem]? {
didSet {
setupRightItems()
updateCommentTriggerViewFrame()
}
}
public var commentTriggerView = CommentTriggerView()
// MARK: - 私有属性
private var leftOffset = 16 // 左偏移
private var rightOffset = -16
private let leftItemsMaxNumber = 1 // 左边Items支持最大数量
private let rightItemsMaxNumber = 3 // 右边Items支持最大数量
private let itemSpacing = 16 // item间距
// MARK: - 公有方法
/// 底部输入框视图初始化方法
/// - Parameters:
/// - placeHolder: 占位文本
/// - triggerBlock: 点击回调
/// - leftButtonItems: 左边Items
/// - rightButtonItems: 右边Items
public init(placeHolder: String?, triggerBlock: (() -> Void)?, leftButtonItems: [BottomButtonItem]? = nil, rightButtonItems: [BottomButtonItem]? = nil) {
super.init(frame: .zero)
setupCommentTriggerView(placeHolder: placeHolder, triggerBlock: triggerBlock)
self.leftButtonItems = leftButtonItems
self.rightButtonItems = rightButtonItems
if leftButtonItems != nil {
setupLeftItems()
}
if rightButtonItems != nil {
setupRightItems()
}
updateCommentTriggerViewFrame()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 私有方法
/// 配置评论视图
/// - Parameters:
/// - placeHolder: 占位文本
/// - triggerBlock: 点击回调
private func setupCommentTriggerView(placeHolder: String?, triggerBlock: (() -> Void)?) {
commentTriggerView.placeHolderText = placeHolder
commentTriggerView.triggerBlock = triggerBlock
addSubview(commentTriggerView)
commentTriggerView.snp.makeConstraints {
(make) in
make.left.equalToSuperview().offset(leftOffset)
make.right.equalToSuperview().offset(rightOffset)
make.top.equalToSuperview().offset(8)
make.bottom.equalToSuperview().offset(-8)
}
}
/// 配置左边Items
private func setupLeftItems() {
if let leftItems = leftButtonItems?.prefix(leftItemsMaxNumber) {
for item in leftItems {
addSubview(item)
}
for item in leftItems {
let itemWidth = item.hasText ? 50 : 24
item.snp.makeConstraints {
(make) in
make.width.equalTo(itemWidth)
make.height.equalTo(24)
make.left.equalToSuperview().offset(leftOffset)
make.top.equalToSuperview().offset(14)
}
leftOffset = leftOffset + itemWidth + itemSpacing
}
}
}
/// 配置右边Items
private func setupRightItems() {
if let rightItems = rightButtonItems?.prefix(rightItemsMaxNumber) {
for item in rightItems {
addSubview(item)
}
for item in rightItems.reversed() {
let itemWidth = item.hasText ? 50 : 24
item.snp.makeConstraints {
(make) in
make.width.equalTo(itemWidth)
make.height.equalTo(20)
make.right.equalToSuperview().offset(rightOffset)
make.top.equalToSuperview().offset(14)
}
rightOffset = rightOffset - itemWidth - itemSpacing
}
}
}
/// 更新评论视图
private func updateCommentTriggerViewFrame() {
commentTriggerView.snp.updateConstraints {
(make) in
make.left.equalToSuperview().offset(leftOffset)
make.right.equalToSuperview().offset(rightOffset)
}
}
}
//
// BottomButtonItem.swift
// QDReaderHelper
//
// Created by wuxueqian on 2020/8/24.
// Copyright © 2020 洋葱. All rights reserved.
//
import UIKit
/*
底部输入框 ButtonItem
类型:带文本 / 不带文本
大小:50*24 / 24*24
*/
class BottomButtonItem: UIView {
// MARK: - 公有属性
public var hasText: Bool = false // 是否附带文本
// MARK: - 私有属性
private var button: UIButton = {
let button = UIButton()
return button
}()
private var label: UILabel = {
let label = UILabel()
label.font = UIFont.qdFont_Caption()
label.textColor = UIColor.qdColor_surface_gray_900()
return label
}()
// MARK: - 公有方法
/// 底部输入框ButtomItem初始化方法
/// - Parameters:
/// - title: 右侧文本
/// - image: 按钮图片
/// - target: 目标
/// - action: 动作
public init(title: String?, image: UIImage?, target: Any?, action: Selector?) {
super.init(frame: .zero)
setupButton(image: image, target: target, action: action)
setupLabel(title: title)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 私有方法
/// 配置按钮
private func setupButton(image: UIImage?, target: Any?, action: Selector?) {
button.setImage(image, for: .normal)
if action != nil {
button.addTarget(target, action: action!, for: .touchUpInside)
}
addSubview(button)
button.snp.makeConstraints {
(make) in
make.width.height.equalTo(24)
}
}
/// 配置右侧文本
private func setupLabel(title: String?) {
if title != nil {
hasText = true
label.text = title!
addSubview(label)
label.snp.makeConstraints {
(make) in
make.left.equalTo(self.button.snp.right).offset(4)
make.height.equalTo(24)
make.right.equalToSuperview()
}
}
}
}
//
// CommentTriggerView.swift
// QDReaderHelper
//
// Created by wuxueqian on 2020/7/29.
// Copyright © 2020 洋葱. All rights reserved.
//
import UIKit
import SnapKit
/*
CommentTriggerView 评论触发器视图
*/
class CommentTriggerView: UIView {
// MARK: - 公有属性
public var triggerBlock: (() -> Void)? {
didSet {
self.triggerButton.addTarget(self, action: #selector(clickButton), for: .touchUpInside)
}
}
public var placeHolderText: String? {
didSet {
if placeHolderText != nil {
self.placeHolderLabel.text = placeHolderText
}
}
}
// MARK: - 私有属性
private lazy var placeHolderLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.qdColor_surface_gray_300()
label.font = UIFont.qdFont_Body2()
label.text = "有想法快点写下来吧..."
return label
}()
private lazy var triggerButton: UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = .clear
return button
}()
private lazy var backView: UIView = {
let view = UIView()
view.layer.masksToBounds = true
view.layer.cornerRadius = 18
view.backgroundColor = UIColor.qdColor_surface_gray_50()
return view
}()
// MARK: - 公有方法
public init(placeHolderText: String?, leftBtns: [BottomButtonItem]? = nil, triggerBlock: (() -> Void)?) {
super.init(frame: .zero)
if let text = placeHolderText {
self.placeHolderText = text
}
if let block = triggerBlock {
self.triggerBlock = block
}
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 私有方法
@objc private func clickButton() {
triggerBlock?()
}
private func setupView() {
addSubview(backView)
addSubview(placeHolderLabel)
addSubview(triggerButton)
self.backView.snp.makeConstraints {
(make) in
make.left.right.top.bottom.equalToSuperview()
}
self.placeHolderLabel.snp.makeConstraints {
(make) in
make.left.equalToSuperview().offset(16)
make.right.equalToSuperview().offset(-16)
make.top.equalToSuperview().offset(6)
make.bottom.equalToSuperview().offset(-6)
}
self.triggerButton.snp.makeConstraints {
(make) in
make.edges.equalToSuperview()
}
}
}