Can't select second item in tableview cell over uiview - ios

anyone please help me, I have a drop down but the I can't select it the second row. I can't figure out why, I try playing with bringSubviewsToFront or back. I try using layer.zPosition it still can't select the second row, but when I choose the first row it work. is it my auto layout setup incorrectly?
here is my ui and code setup
// 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)

Because of the hit-test mechanism
You add the dropView on the Button GDropdownSchedule
The layout is
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)
])
From the looking and the existing code,
dropView's frame is out of the Button GDropdownSchedule's bounds Partly.
So u can see it , and your clicking does not work.
To override the hit-test mechanism is OK
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
}
}
From Apple's Doc
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.

Related

TableView didSelectRowAt not being called when nested in views

I have the following structure UIViewController -> UIView -> UIView -> UITableView (it's a dropdown menu), and the method didSelectRowAt is not being called, but if I skip the first view (that after VC), everything working perfectly. I saw a similar question here where was stated that you should use the method bringSubviewToFront but I tried that and it's not working (maybe I did it wrong).
Here is my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let someView = someView()
someView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(someView)
}
}
class someView: UIView {
public lazy var button: DropDownButton = {
let button = DropDownButton(frame: .init(x: 0, y: 0, width: 100, height: 40))
button.setTitle("Colors", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.dropView.dropDownOptions = ["1","2","1","2"]
button.dropView.delegate = self
return button
}()
init() {
super.init(frame: .init(x: 0, y: 0, width: 300, height: 100))
addSubview(button)
addSubview(scrollButtons)
setUpConstraints()
}
}
class DropDownButton: UIButton {
public var dropView = DropDownView()
private var height = NSLayoutConstraint()
private var isOpen = false
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.darkGray
dropView = DropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
dropView.translatesAutoresizingMaskIntoConstraints = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToSuperview() {
self.superview?.addSubview(dropView)
self.superview?.bringSubviewToFront(dropView)
dropView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
dropView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
dropView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
height = dropView.heightAnchor.constraint(equalToConstant: 0)
}
func dismissDropDown() {
isOpen = false
NSLayoutConstraint.deactivate([self.height])
self.height.constant = 0
NSLayoutConstraint.activate([self.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()
}, completion: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isOpen == false {
isOpen = true
NSLayoutConstraint.deactivate([self.height])
self.height.constant = self.dropView.tableView.contentSize.height
NSLayoutConstraint.activate([self.height])
UIView.animate(withDuration: 0.3,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.5,
options: .curveEaseInOut,
animations: {
self.dropView.layoutIfNeeded()
self.dropView.center.y += self.dropView.frame.height / 2
}, completion: nil)
} else {
isOpen = false
NSLayoutConstraint.deactivate([self.height])
self.height.constant = 0
NSLayoutConstraint.activate([self.height])
UIView.animate(
withDuration: 0.3,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.5,
options: .curveEaseInOut,
animations: {
self.dropView.center.y -= self.dropView.frame.height / 2
self.dropView.layoutIfNeeded()
}, completion: nil)
}
}
}
class DropDownView: UIView {
var dropDownOptions = [String]()
var tableView = UITableView()
weak var delegate: DropDownDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
tableView.backgroundColor = UIColor.darkGray
self.backgroundColor = UIColor.darkGray
tableView.delegate = self
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.leftAnchor.constraint(equalTo: self.leftAnchor),
tableView.rightAnchor.constraint(equalTo: self.rightAnchor),
tableView.topAnchor.constraint(equalTo: self.topAnchor),
tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension DropDownView: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dropDownOptions.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = dropDownOptions[indexPath.row]
cell.backgroundColor = UIColor.darkGray
return cell
}
}
extension DropDownView: UITableViewDelegate {
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print("cell pressed")
self.delegate?.dropDownPressed(string: dropDownOptions[indexPath.row])
self.tableView.deselectRow(at: indexPath, animated: true)
}
}

UITableView separator color not changing

I'm trying to create a drop-down menu. In this drop-down menu, I have a UIView which the user taps on to drop down a UITableView. In the process of creating it, I tried to change the separator color to clear. However, it's not working. I have tried settings it different colors all to no avail, but for some reason when I try to set its edge inset it works. Can someone help me out?
private var selectedBackgroundColor : UIColor = UIColor(red: 131/255, green: 43/255, blue: 205/255, alpha: 1.0)
private var unSelectedBackgroundColor : UIColor = UIColor(red: 178/255, green: 90/255, blue: 253/255, alpha: 1.0)
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInitializer()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.commonInitializer()
}
private func commonInitializer() {
self.backgroundColor = self.unSelectedBackgroundColor
self.layer.cornerRadius = self.bounds.height/2
let shadowColor = UIColor(red: 0xC8, green: 0xC6, blue: 0xC6)
self.layer.applySketchShadow(color: shadowColor, alpha: 0.5, x: 0, y: 2, blur: 5, spread: 0)
self.itemTableView.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
self.itemTableView.translatesAutoresizingMaskIntoConstraints = false
self.itemTableView.delegate = self
self.itemTableView.dataSource = self
self.itemTableView.showsVerticalScrollIndicator = false
self.itemTableView.separatorColor = UIColor.clear
self.itemTableView.backgroundColor = self.unSelectedBackgroundColor
}
override func didMoveToSuperview() {
self.superview?.addSubview(itemTableView)
self.superview?.bringSubviewToFront(itemTableView)
//Drop down table view constraints
self.itemTableView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
self.itemTableView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
self.itemTableView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
self.tableViewHeight = self.itemTableView.heightAnchor.constraint(equalToConstant: 0)
}
/**
Changes the drop down button view and table view to the selected color
*/
private func changeToSelectedBackgroundColor() {
self.backgroundColor = self.selectedBackgroundColor
self.itemTableView.backgroundColor = self.selectedBackgroundColor
}
/**
Changes only the drop down button view to the unselected color. Changes the table view to white
*/
private func changeToUnSelectedBackgroundColor() {
self.backgroundColor = self.unSelectedBackgroundColor
self.itemTableView.backgroundColor = UIColor.white
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = self.items[indexPath.row]
cell.backgroundColor = UIColor.clear
cell.textLabel?.textColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.itemTableView.deselectRow(at: indexPath, animated: true)
self.retractDropDownList()
}
#objc func buttonTapped() {
self.flashLabel()
if isExtended {
self.retractDropDownList()
} else {
self.expandDropDownList()
}
}
private func expandDropDownList() {
isExtended = true
self.delegate?.dropDownViewExtended()
NSLayoutConstraint.deactivate([self.tableViewHeight])
self.tableViewHeight.constant = 150.0
NSLayoutConstraint.activate([
self.tableViewHeight])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.changeToSelectedBackgroundColor()
self.itemTableView.layoutIfNeeded()
self.layer.cornerRadius = 0.0
self.itemTableView.center.y += self.itemTableView.frame.height/2
}, completion: nil)
}
private func retractDropDownList() {
isExtended = false
self.delegate?.dropDownViewRetracted()
NSLayoutConstraint.deactivate([self.tableViewHeight])
self.tableViewHeight.constant = 0.0
NSLayoutConstraint.activate([
self.tableViewHeight])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.changeToUnSelectedBackgroundColor()
self.itemTableView.center.y -= self.itemTableView.frame.height/2
self.itemTableView.layoutIfNeeded()
self.layer.cornerRadius = self.bounds.height/2
}, completion: nil)
}
}

My UITableView crashes when I add a gradient background?

I have a UITableView under a UIViewController with a custom cell. The text for the UILabel in each cell is held in an array of strings. I’m coding in Swift Playgrounds, and when I run the Playground with an empty array it works fine (there aren’t an cells, of course, but the playground does run). When I populate the array, I get the error “there as a problem running this page... check your code...”. When I step through the code, it gets stuck at the line:
view.addSubview(gradientView)
What am I doing wrong?
import UIKit
import PlaygroundSupport
class ViewController: UITableViewController {
// Array that holds menu items
var menuItems = ["option 1","option 2","option 3"]
override func viewDidLoad() {
super.viewDidLoad()
// Add a gradient background
// Set height, width to view height, width
var gradientView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame.size = gradientView.frame.size
// Set colors
gradientLayer.colors = [UIColor(red: 253/255, green: 94/255, blue: 172/255, alpha: 1).cgColor, UIColor(red: 121/255, green: 73/255, blue: 242/255, alpha: 1).cgColor]
// Skew gradient (diagonally)
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
// Rasterize to improve performance
gradientLayer.shouldRasterize = true
//Add gradient
gradientView.layer.addSublayer(gradientLayer)
view.addSubview(gradientView)
// Reguster custom cell
tableView.register(MenuItemCell.self, forCellReuseIdentifier: "cell_1")
// Turn off seperators
tableView.separatorStyle = .none
// Set header height
tableView.sectionHeaderHeight = 75
}
// Custom header
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
let customView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 75))
customView.backgroundColor = .clear //UIColor(white: 0.9, alpha: 1)
let button = UIButton(type: .custom)
button.setTitle("😁", for: .normal)
button.frame = CGRect(x: 20, y: 20, width: 50, height: 50)
button.layer.cornerRadius = 25
button.layer.shadowRadius = 8.0
button.layer.shadowColor = UIColor.black.cgColor
button.layer.shadowOffset = CGSize(width: 0, height: 0)
button.layer.shadowOpacity = 0.5
let blur = UIVisualEffectView(effect: UIBlurEffect(style:
UIBlurEffect.Style.light))
blur.frame = button.bounds
blur.isUserInteractionEnabled = false //This allows touches to forward to the button.
button.insertSubview(blur, at: 0)
customView.addSubview(button)
return customView
}
#objc func updateView(){
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell_1", for: indexPath) as! MenuItemCell
cell.selectionStyle = .none
//cell.messageLabel.text = textMessages[indexPath.row]
cell.bubbleBackgroundView.backgroundColor = UIColor(white: 0.9, alpha: 1)
return cell
}
}
class MenuItemCell: UITableViewCell {
let optionLabel = UILabel()
let bubbleBackgroundView = UIView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
bubbleBackgroundView.layer.shadowOpacity = 0.35
bubbleBackgroundView.layer.shadowRadius = 6
bubbleBackgroundView.layer.shadowOffset = CGSize(width: 0, height: 0)
bubbleBackgroundView.layer.shadowColor = UIColor.black.cgColor
bubbleBackgroundView.layer.cornerRadius = 25
bubbleBackgroundView.translatesAutoresizingMaskIntoConstraints = false
addSubview(bubbleBackgroundView)
addSubview(optionLabel)
optionLabel.numberOfLines = 0
optionLabel.translatesAutoresizingMaskIntoConstraints = false
// lets set up some constraints for our label
let constraints = [optionLabel.topAnchor.constraint(equalTo: topAnchor, constant: 32),
optionLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32),
optionLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -32),
optionLabel.widthAnchor.constraint(equalToConstant: 250),
bubbleBackgroundView.topAnchor.constraint(equalTo: optionLabel.topAnchor, constant: -16),
bubbleBackgroundView.leadingAnchor.constraint(equalTo: optionLabel.leadingAnchor, constant: -16),
bubbleBackgroundView.bottomAnchor.constraint(equalTo: optionLabel.bottomAnchor, constant: 16),
bubbleBackgroundView.trailingAnchor.constraint(equalTo: optionLabel.trailingAnchor, constant: 16),
]
NSLayoutConstraint.activate(constraints)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
PlaygroundPage.current.liveView = ViewController()

Dropdown menu UIView opened from button in UITableviewCell not clickable outside of cell bounds

I am trying to make a button open up a dropdown menu styled UIView inside of a custom UITableViewCell. And it does open the UIView containing the other buttons. Great. However, the only clickable part is the tiny little bit of "1" inside the UITableViewCell. The rest of the dropdown menu is not clickable and you can click through it to the cell below. How can I make the button in the custom UITableViewCell open up the UIView with the dropdown menu and have each button inside the UIView clickable?
Here is what it's looking like now.
//The button inside the UITableViewCell:
class PriorityButton: UIButton, DropDownDelegate {
var dropDownView = DropDownView()
var height = NSLayoutConstraint()
var isOpen = false
override init(frame: CGRect) {
super.init(frame: frame)
dropDownView = DropDownView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
dropDownView.delegate = self
dropDownView.translatesAutoresizingMaskIntoConstraints = false
// button.setImage(UIImage(named: "UnChecked"), for: .normal)
// button.setImage(UIImage(named: "Checked"), for: .selected)
self.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
self.setTitleColor(.black, for: .normal)
self.backgroundColor = UIColor.white
self.layer.borderWidth = 2
self.layer.borderColor = UIColor.black.cgColor
self.titleLabel?.font = UIFont.init(name: "Avenir Next", size: 24)
}
override func didMoveToSuperview() {
self.superview?.addSubview(dropDownView)
self.superview?.bringSubviewToFront(dropDownView)
dropDownView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
dropDownView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
dropDownView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
height = dropDownView.heightAnchor.constraint(equalToConstant: 0)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isOpen == false {
isOpen = true
NSLayoutConstraint.deactivate([self.height])
if self.dropDownView.priorityTableView.contentSize.height > 300 {
self.height.constant = 300
} else {
self.height.constant = self.dropDownView.priorityTableView.contentSize.height
}
NSLayoutConstraint.activate([self.height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropDownView.layoutIfNeeded()
self.dropDownView.center.y += self.dropDownView.frame.height / 2
}, completion: nil)
} else {
isOpen = false
NSLayoutConstraint.deactivate([self.height])
self.height.constant = 0
NSLayoutConstraint.activate([self.height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropDownView.center.y -= self.dropDownView.frame.height / 2
self.dropDownView.layoutIfNeeded()
}, completion: nil)
}
}
func dismissDropDown() {
isOpen = false
NSLayoutConstraint.deactivate([self.height])
self.height.constant = 0
NSLayoutConstraint.activate([self.height])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.dropDownView.center.y -= self.dropDownView.frame.height / 2
self.dropDownView.layoutIfNeeded()
}, completion: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func dropDownPressed(string: String) {
self.setTitle(string, for: .normal)
self.dismissDropDown()
}
}
// The Drop Down Menu view
class DropDownView: UIView, UITableViewDelegate, UITableViewDataSource {
let priorityLevel = ["1", "2", "3", "4", "5"]
var priorityTableView = UITableView()
var delegate: DropDownDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .white
priorityTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellID")
priorityTableView.backgroundColor = .white
priorityTableView.delegate = self
priorityTableView.dataSource = self
priorityTableView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(priorityTableView)
priorityTableView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
priorityTableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
priorityTableView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
priorityTableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return priorityLevel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath)
cell.textLabel?.text = priorityLevel[indexPath.row]
cell.backgroundColor = .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("test")
}
}
Expected results:
I want to click on the "1" button in the custom UITableViewCell and it show the dropdown menu UIView and be able to click on the buttons contained within the dropdown menu.
I think the problem is that the drop down is added to the super view of the cell (aka the tableView) and the delegate of the dropdown is assigned to the cell itself hence it won't respond to the tap gesture recognizer since the table view is not the delegate of it and the tap should occur on the cell, try adding it to the subView of the cell instead of the superView maybe that'll work. Good luck 👍

UIView animation causing label to twitch

I have an IconView class that I use as a custom image for a Google Maps marker. All of the print statements show that the code is correctly executing. However, the "12:08" UILabel in circleView keeps on growing and shrinking (i.e. twitching). I can't figure out what the problem might be. I've tried manually setting the the font in the completion block, commenting out the adjustsFontSizeToFitWidth, changing the circleView to a UIButton.
import UIKit
class IconView: UIView {
var timeLabel: UILabel!
var circleView: UIView!
var clicked: Bool!
//constants
let circleViewWidth = 50.0
let circleViewHeight = 50.0
override init(frame:CGRect) {
super.init(frame : frame)
self.backgroundColor = UIColor(red: 47/255, green: 49/255, blue: 53/255, alpha: 0.0)
clicked = false
if !clicked {
//MAIN CIRCLE
print("init circle view")
circleView = UIView(frame: CGRect(x:0, y:0, width:circleViewWidth, height:circleViewHeight))
circleView.backgroundColor = UIColor(red: 47/255, green: 49/255, blue: 53/255, alpha: 1.0)
circleView.layer.cornerRadius = circleView.frame.size.height / 2.0
circleView.layer.masksToBounds = true
self.addSubview(circleView)
timeLabel = UILabel(frame: CGRect(x: 0, y: 0, width: circleViewWidth, height: circleViewHeight/3.0))
timeLabel.center = circleView.center
timeLabel.text = "12:08"
timeLabel.textAlignment = .center
timeLabel.textColor = .white
timeLabel.numberOfLines = 0
timeLabel.font = UIFont.systemFont(ofSize: 11)
timeLabel.font = UIFont.boldSystemFont(ofSize: 11)
timeLabel.adjustsFontSizeToFitWidth = true
circleView.addSubview(timeLabel)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
let iconView = marker.iconView as! IconView
print("going to start animating")
if !iconView.clicked {
UIView.animate(withDuration: 0.2, animations: {
print("making this bigger now")
iconView.circleView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
})
{ (finished:Bool) -> Void in
print("DONE")
iconView.clicked = true
}
}
return true
}

Resources