不能 select tableview 单元格中的第二个项目超过 uiview
Can't select second item in tableview cell over uiview
任何人都请帮助我,我有一个下拉列表,但我不能 select 第二行。我不明白为什么,我尝试使用 bringSubviewsToFront 或返回。我尝试使用 layer.zPosition 它仍然不能 select 第二行,但是当我选择第一行时它起作用了。是我的自动布局设置不正确吗?
这是我的 ui 和代码设置
// This is my custom Button
class GDropdownSchedule: UIButton {
let headerLbl = GTitleLabel(name: "Schedule Type".localized(), fontSize: 13, color: #colorLiteral(red: 0.4588235294, green: 0.4941176471, blue: 0.5647058824, alpha: 1))
let bodyLbl = GSubtitleLabel(name: "Additional Note".localized(), fontSize: 16, color: #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1))
let dropDownIV = GIconImageView(img: #imageLiteral(resourceName: "down-chevron"))
var isOpen = false
let dropView = DropDownView()
var delegate: AddScheduleVCDelegate?
var height: NSLayoutConstraint!
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
layer.cornerRadius = 5
layer.borderWidth = 1
layer.borderColor = #colorLiteral(red: 0.9411764706, green: 0.9411764706, blue: 0.9450980392, alpha: 1)
dropView.completion = { text in
self.bodyLbl.text = text
self.bodyLbl.font = UIFont(name: "NunitoSans-Regular", size: 12)
self.delegate?.toggleHide(selected: text)
self.dismissDropDown()
}
}
override func didMoveToSuperview() {
addSubview(headerLbl)
headerLbl.anchor(top: topAnchor, trailing: nil, bottom: nil, leading: leadingAnchor, topPadding: 10, rightPadding: 0, bottomPadding: 0, leftPadding: 10, width: 70, height: 18)
addSubview(bodyLbl)
bodyLbl.anchor(top: headerLbl.bottomAnchor, trailing: nil, bottom: bottomAnchor, leading: leadingAnchor, topPadding: 2, rightPadding: 10, bottomPadding: 10, leftPadding: 10, width: 0, height: 0)
addSubview(dropDownIV)
dropDownIV.tintColor = #colorLiteral(red: 0.2549019608, green: 0.3019607843, blue: 0.3568627451, alpha: 1)
dropDownIV.anchor(top: nil, trailing: trailingAnchor, bottom: bottomAnchor, leading: nil, topPadding: 0, rightPadding: 18, bottomPadding: 17, leftPadding: 0, width: 12, height: 10)
addSubview(dropView)
dropView.translatesAutoresizingMaskIntoConstraints = false
dropView.layer.zPosition = 1
height = dropView.heightAnchor.constraint(equalToConstant: 0)
NSLayoutConstraint.activate([
dropView.topAnchor.constraint(equalTo: headerLbl.bottomAnchor),
dropView.leadingAnchor.constraint(equalTo: leadingAnchor),
dropView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isOpen == false {
isOpen = true
NSLayoutConstraint.deactivate([height])
if self.dropView.tableView.contentSize.height > 150 {
height.constant = 150
} else {
height.constant = dropView.tableView.contentSize.height
}
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.layoutIfNeeded()
self.dropView.center.y += self.dropView.frame.height / 2
})
} else {
isOpen = false
NSLayoutConstraint.deactivate([height])
height.constant = 0
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.center.y -= self.dropView.frame.height / 2
self.dropView.layoutIfNeeded()
})
}
}
func dismissDropDown() {
isOpen = false
NSLayoutConstraint.deactivate([height])
height.constant = 0
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.center.y -= self.dropView.frame.height / 2
self.dropView.layoutIfNeeded()
})
}
}
class DropDownView: UIView, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var options = [String]()
var completion: ((String) -> Void)?
var isHideSchedule = false
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
translatesAutoresizingMaskIntoConstraints = false
addSubview(tableView)
tableView.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
tableView.anchor(top: topAnchor, trailing: trailingAnchor, bottom: bottomAnchor, leading: leadingAnchor, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: 0, height: 0)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = options[indexPath.row]
cell.textLabel?.font = UIFont(name: "NunitoSans-Regular", size: 12)
cell.textLabel?.textColor = #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1)
cell.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
completion?(options[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
}
// This is in my viewController, the chooseScheduleDropDown is my customButton
[chooseScheduleDropDown, entryView, chooseDateView, chooseClass, startTimeView, endTimeView, descriptionView, saveBtn].forEach {
v in
v.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(v)
}
scrollView.insertSubview(entryView, belowSubview: chooseScheduleDropDown)
因为命中测试机制
您在按钮上添加 dropView GDropdownSchedule
布局是
addSubview(dropView)
dropView.translatesAutoresizingMaskIntoConstraints = false
dropView.layer.zPosition = 1
height = dropView.heightAnchor.constraint(equalToConstant: 0)
NSLayoutConstraint.activate([
dropView.topAnchor.constraint(equalTo: headerLbl.bottomAnchor),
dropView.leadingAnchor.constraint(equalTo: leadingAnchor),
dropView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
从现有代码来看,
dropView 的框架部分超出 Button GDropdownSchedule
的边界。
所以你可以看到它,你点击不起作用。
覆盖命中测试机制即可
class GDropdownSchedule: UIButton {
// ...
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
let dropViewF = dropView.frame
var index = 9
if bounds.contains(point){
index = 0
}
if dropViewF.contains(point){
index = 1
}
switch index {
case 0:
for subV in subviews.reversed(){
let realPoint = subV.convert(point, from: self)
let hit = subV.hitTest(realPoint, with: event)
if let v = hit{
return v
}
}
return self
case 1:
if dropView.alpha > 0.01{
let realPoint = dropView.convert(point, from: self)
let hit = dropView.hitTest(realPoint, with: event)
if let v = hit{
return v
}
}
default:
()
}
return nil
}
}
hitTest(_:with:)
This method traverses the view hierarchy by calling the
point(inside:with:) method of each subview to determine which subview
should receive a touch event.
If point(inside:with:) returns true,
then the subview’s hierarchy is similarly traversed until the
frontmost view containing the specified point is found. If a view does
not contain the point, its branch of the view hierarchy is ignored.
You rarely need to call this method yourself, but you might override
it to hide touch events from subviews.
任何人都请帮助我,我有一个下拉列表,但我不能 select 第二行。我不明白为什么,我尝试使用 bringSubviewsToFront 或返回。我尝试使用 layer.zPosition 它仍然不能 select 第二行,但是当我选择第一行时它起作用了。是我的自动布局设置不正确吗?
这是我的 ui 和代码设置
// This is my custom Button
class GDropdownSchedule: UIButton {
let headerLbl = GTitleLabel(name: "Schedule Type".localized(), fontSize: 13, color: #colorLiteral(red: 0.4588235294, green: 0.4941176471, blue: 0.5647058824, alpha: 1))
let bodyLbl = GSubtitleLabel(name: "Additional Note".localized(), fontSize: 16, color: #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1))
let dropDownIV = GIconImageView(img: #imageLiteral(resourceName: "down-chevron"))
var isOpen = false
let dropView = DropDownView()
var delegate: AddScheduleVCDelegate?
var height: NSLayoutConstraint!
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
layer.cornerRadius = 5
layer.borderWidth = 1
layer.borderColor = #colorLiteral(red: 0.9411764706, green: 0.9411764706, blue: 0.9450980392, alpha: 1)
dropView.completion = { text in
self.bodyLbl.text = text
self.bodyLbl.font = UIFont(name: "NunitoSans-Regular", size: 12)
self.delegate?.toggleHide(selected: text)
self.dismissDropDown()
}
}
override func didMoveToSuperview() {
addSubview(headerLbl)
headerLbl.anchor(top: topAnchor, trailing: nil, bottom: nil, leading: leadingAnchor, topPadding: 10, rightPadding: 0, bottomPadding: 0, leftPadding: 10, width: 70, height: 18)
addSubview(bodyLbl)
bodyLbl.anchor(top: headerLbl.bottomAnchor, trailing: nil, bottom: bottomAnchor, leading: leadingAnchor, topPadding: 2, rightPadding: 10, bottomPadding: 10, leftPadding: 10, width: 0, height: 0)
addSubview(dropDownIV)
dropDownIV.tintColor = #colorLiteral(red: 0.2549019608, green: 0.3019607843, blue: 0.3568627451, alpha: 1)
dropDownIV.anchor(top: nil, trailing: trailingAnchor, bottom: bottomAnchor, leading: nil, topPadding: 0, rightPadding: 18, bottomPadding: 17, leftPadding: 0, width: 12, height: 10)
addSubview(dropView)
dropView.translatesAutoresizingMaskIntoConstraints = false
dropView.layer.zPosition = 1
height = dropView.heightAnchor.constraint(equalToConstant: 0)
NSLayoutConstraint.activate([
dropView.topAnchor.constraint(equalTo: headerLbl.bottomAnchor),
dropView.leadingAnchor.constraint(equalTo: leadingAnchor),
dropView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isOpen == false {
isOpen = true
NSLayoutConstraint.deactivate([height])
if self.dropView.tableView.contentSize.height > 150 {
height.constant = 150
} else {
height.constant = dropView.tableView.contentSize.height
}
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.layoutIfNeeded()
self.dropView.center.y += self.dropView.frame.height / 2
})
} else {
isOpen = false
NSLayoutConstraint.deactivate([height])
height.constant = 0
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.center.y -= self.dropView.frame.height / 2
self.dropView.layoutIfNeeded()
})
}
}
func dismissDropDown() {
isOpen = false
NSLayoutConstraint.deactivate([height])
height.constant = 0
NSLayoutConstraint.activate([height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropView.center.y -= self.dropView.frame.height / 2
self.dropView.layoutIfNeeded()
})
}
}
class DropDownView: UIView, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var options = [String]()
var completion: ((String) -> Void)?
var isHideSchedule = false
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
translatesAutoresizingMaskIntoConstraints = false
addSubview(tableView)
tableView.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
tableView.anchor(top: topAnchor, trailing: trailingAnchor, bottom: bottomAnchor, leading: leadingAnchor, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: 0, height: 0)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = options[indexPath.row]
cell.textLabel?.font = UIFont(name: "NunitoSans-Regular", size: 12)
cell.textLabel?.textColor = #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1)
cell.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
completion?(options[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
}
// This is in my viewController, the chooseScheduleDropDown is my customButton
[chooseScheduleDropDown, entryView, chooseDateView, chooseClass, startTimeView, endTimeView, descriptionView, saveBtn].forEach {
v in
v.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(v)
}
scrollView.insertSubview(entryView, belowSubview: chooseScheduleDropDown)
因为命中测试机制
您在按钮上添加 dropView GDropdownSchedule
布局是
addSubview(dropView)
dropView.translatesAutoresizingMaskIntoConstraints = false
dropView.layer.zPosition = 1
height = dropView.heightAnchor.constraint(equalToConstant: 0)
NSLayoutConstraint.activate([
dropView.topAnchor.constraint(equalTo: headerLbl.bottomAnchor),
dropView.leadingAnchor.constraint(equalTo: leadingAnchor),
dropView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
从现有代码来看,
dropView 的框架部分超出 Button GDropdownSchedule
的边界。
所以你可以看到它,你点击不起作用。
覆盖命中测试机制即可
class GDropdownSchedule: UIButton {
// ...
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
let dropViewF = dropView.frame
var index = 9
if bounds.contains(point){
index = 0
}
if dropViewF.contains(point){
index = 1
}
switch index {
case 0:
for subV in subviews.reversed(){
let realPoint = subV.convert(point, from: self)
let hit = subV.hitTest(realPoint, with: event)
if let v = hit{
return v
}
}
return self
case 1:
if dropView.alpha > 0.01{
let realPoint = dropView.convert(point, from: self)
let hit = dropView.hitTest(realPoint, with: event)
if let v = hit{
return v
}
}
default:
()
}
return nil
}
}
hitTest(_:with:)
This method traverses the view hierarchy by calling the point(inside:with:) method of each subview to determine which subview should receive a touch event.
If point(inside:with:) returns true, then the subview’s hierarchy is similarly traversed until the frontmost view containing the specified point is found. If a view does not contain the point, its branch of the view hierarchy is ignored.
You rarely need to call this method yourself, but you might override it to hide touch events from subviews.