在我的自定义tableviewcell上,我有一个按钮,用户可以按该按钮在选定和未选定之间切换。这只是一个简单的UIButton,此按钮包含在我的customtableviewcell中,作为插座。
import UIKit
class CustomCellAssessment: UITableViewCell {
@IBOutlet weak var name: UILabel!
@IBOutlet weak var dateTaken: UILabel!
@IBOutlet weak var id: UILabel!
@IBOutlet weak var score: UILabel!
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func selectButton(_ sender: UIButton) {
if sender.isSelected{
sender.isSelected = false
}else{
sender.isSelected = true
}
}
}
奇怪的是,当我在第一个单元格上按一个按钮时,它随后在同一表视图中的另一个单元格(视图外)上向下选择了8个单元格的按钮。每个单元格都有自己的按钮,但是好像使用dequeReusableCell导致系统以这种方式运行一样。为什么这样做,并且与UIbutton在tableviewcell上的工作方式有关?
谢谢
答案 0 :(得分:1)
点击按钮时,将设置按钮的选定状态。当单元被重用时,按钮仍处于选中状态-您无需执行任何操作即可重置或更新该状态。
如果按钮选择与表格单元格选择分开,那么您需要跟踪所选按钮的索引路径作为数据模型的一部分,然后在{{ 1}}。
表视图将仅创建所需的单元格,以显示一屏左右的信息。之后,单元将被重用。如果某个单元格滚动到屏幕顶部之外,则表格视图会将其置于重用队列中,然后在滚动时需要在底部显示新行时,它将其从队列中拉出并提供给您tableView(_: cellForRowAt:)
。
您在此处获得的单元将与您之前使用8行左右的单元完全相同,完全由您决定。您可以在tableView(_: cellForRowAt:)
中做到这一点,并且通过实现cellForRow
也可以在单元格本身中获得机会,这在单元格出队之前就被调用。
答案 1 :(得分:1)
每个单元格都有其自己的按钮,但这就像使用dequeReusableCell导致系统以这种方式运行一样。
错了。 UITableViewCells是可重用的,因此,如果您的tableView有8个可见的单元格,则在加载第9个单元格时,单元格nr 1将被重用。
解决方案:您需要跟踪细胞状态。调用方法cellForRowAtIndexPath
时,您需要从头开始配置单元格。
您可能在ViewController中有一个包含单元格状态的小数组:
var cellsState: [CellState]
并在其中存储每个indexPath的选定状态。然后在cellForRowAtIndexPath中,用状态配置单元格。
cell.selected = self.cellsState[indexPath.row].selected
因此,我要做的概述是:
1-在cellForRowAtIndexPath
上,我将设置
cell.button.tag = indexPath.row
cell.selected = cellsState[indexPath.row].selected
2-将IBAction移至ViewController或TableViewController
3-调用click方法时,更新单元格的选定状态
self.cellsState[sender.tag].selected = true
请记住,始终将整个单元配置为cellForRowAtIndexPath
编辑:
import UIKit
struct CellState {
var selected:Bool
init(){
selected = false
}
}
class MyCell: UITableViewCell {
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
self.button.setTitleColor(.red, for: .selected)
self.button.setTitleColor(.black, for: .normal)
}
}
class ViewController: UIViewController, UITableViewDataSource {
var cellsState:[CellState] = []
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Add state for 5 cells.
for _ in 0...5 {
self.cellsState.append(CellState())
}
}
@IBAction func didClick(_ sender: UIButton) {
self.cellsState[sender.tag].selected = true
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsState.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MyCell
cell.button.isSelected = self.cellsState[indexPath.row].selected
cell.button.tag = indexPath.row
return cell
}
}
答案 2 :(得分:0)
在您的~> cs sbt/sbt --branch 1.2.1
Repository not found on github
中,采取措施单击按钮并添加目标
tableView(_: cellForRowAt:)
在目标方法中,使用以下几行来获取cell.button.addTarget(self, action: #selector(self.selectedButton), for: .touchUpInside)
indexPath
然后使用该func selectedButton(sender: UIButton){
let hitPoint: CGPoint = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath: NSIndexPath = self.tableView.indexPathForRow(at: hitPoint)! as NSIndexPath
}
完成您的工作。
实际上,您的方法找不到单击indexPath
按钮的位置,这就是为什么您无法使用所需按钮的原因。
答案 3 :(得分:0)
解决问题的一种方法如下
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string dbPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlite($@"Data Source={dbPath}\sqlite\.sample.sqlite");
Batteries.Init();
base.OnConfiguring(optionsBuilder);
}
}
1. First create a protocol to know when button is clicked
protocol MyCellDelegate: class {
func cellButtonClicked(_ indexPath: IndexPath)
}
2. Now in your cell class, you could do something like following
class MyCell: UITableViewCell {
var indexPath: IndexPath?
weak var cellButtonDelegate: MyCellDelegate?
func configureCell(with value: String, atIndexPath indexPath: IndexPath, selected: [IndexPath]) {
self.indexPath = indexPath //set the indexPath
self.textLabel?.text = value
if selected.contains(indexPath) {
//this one is selected so do the stuff
//here we will chnage only the background color
backgroundColor = .red
self.textLabel?.textColor = .white
} else {
//unselected
backgroundColor = .white
self.textLabel?.textColor = .red
}
}
@IBAction func buttonClicked(_ sender: UIButton) {
guard let delegate = cellButtonDelegate, let indexPath = indexPath else { return }
delegate.cellButtonClicked(indexPath)
}
}
3. Now in your controller. I'm using UItableViewController here