问题
I have a tableView where when a user taps on that cell, I want the cell to expand and fill the entire screen with that color. Currently, it does scale to fill the entire screen but the cells above it will also show. The colors come from an API and each cell changes color when the user taps the "Generate" button. Due to how the API's JSON file is structured, I only want 5 colors on the screen at a time.
I can't figure out why the cells above it don't move upwards or how I can move the clicked cell to the top of the screen. I've tried offsetting the coordinates of the tapped cell and changing its frame size to be the height of the tableView tappedCell.bounds.size = CGSize(width: UIScreen.main.bounds.width, height: self.paletteTableView.bounds.height)
but when I click the 1st or 2nd cells from the top, the screen doesn't fill all the way to the bottom.
I've also tried animating from a UIView (called colorDetailsView
here) but wasn't able to successfully get it to animate from the center of each cell that's tapped on, only from the center of the screen.
The animation happens here:
@objc func userTap(sender: UITapGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.ended {
let tapLocation = sender.location(in: self.paletteTableView)
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) {
UIView.animate(withDuration: 0.5, animations: {
switch self.currentAnimation {
case 0:
tappedCell.transform = CGAffineTransform(scaleX: 1, y: 50)
//...
case 1:
tappedCell.transform = .identity
default: break
}
} )
currentAnimation += 1
if currentAnimation > 1 {
currentAnimation = 0
} } } } }
Full code:
class PaletteController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let tableView = UITableView()
var colorPalette = [Color]()
var currentAnimation = 0
let colorDetailsView: UIView = {
let view = UIView()
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.isScrollEnabled = false
\\...
view.addSubview(colorDetailsView)
}
//Color cell expands to fill the screen of that color when user taps on the cell
@objc func userTap(sender: UITapGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.ended {
let tapLocation = sender.location(in: self.tableView)
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) {
UIView.animate(withDuration: 0.5, animations: {
//When user taps on a cell, it is scaled to fill the screen with that color
switch self.currentAnimation {
case 0:
tappedCell.transform = CGAffineTransform(scaleX: 1, y: 50)
for i in 0..<self.colorPalette.count {
if tapIndexPath.row == i {
self.colorDetailsView.backgroundColor = UIColor(hexString: self.colorPalette[i])
}
}
case 1:
tappedCell.transform = .identity
default: break
}
} )
currentAnimation += 1
if currentAnimation > 1 {
currentAnimation = 0
}
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"ColorCell", for: indexPath)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(userTap(sender:)))
cell.addGestureRecognizer(tapGesture)
cell.isUserInteractionEnabled = true
//Assigns a new color to each row. Colors are converted from HEX to RGB
for i in 0..<colorPalette.count {
if tapIndexPath.row == i {
cell.backgroundColor = UIColor(hexString: colorPalette[i])
}
}
return cell
}
}
I know the cell is scaling when I set tableView.isScrollEnabled
to true, as shown below. Each cell should end up filling the whole screen and not get covered by any other cells, like the top-most cell. Ideally, I'd like the tableView to not scroll, but I'm not sure if the top cells will "move up" if scroll is disable.
Any help is appreciated!
回答1:
The cells are after all sub-views of the table view. You need to bring the tapped cell at the front of the sub-view list.
I would suggest adding
tableView.bringSubviewToFront(tappedCell)
just after the line
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) {
.
See if this works!
来源:https://stackoverflow.com/questions/61847668/scale-tableview-cell-with-cgaffinetransform-to-cover-entire-screen