我想創建一個可展開的表格視圖單元格,在單擊單元格的特定部分時,我想影片和展開單元格。
我可以使用默認影片展開和折疊,這基本上會淡化視圖變化。但我想為指示器影像上的旋轉設定影片并展開單元格。
這是目前影片的方式。

這是我的表格視圖代碼
class ExpandableTableView: UITableView {
var status:[Bool] = [Bool].init(repeating: false, count: 10)
override init(frame: CGRect, style: UITableView.Style) {
super.init(frame: frame, style: style)
self.registerCell()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.registerCell()
}
func registerCell() {
self.register(UINib(nibName: "DemoTableViewCell", bundle: .main), forCellReuseIdentifier: "DemoTableViewCell")
self.rowHeight = UITableView.automaticDimension
self.delegate = self
self.dataSource = self
}
}
extension ExpandableTableView: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return status.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "DemoTableViewCell") as? DemoTableViewCell else {
return UITableViewCell()
}
cell.setHeader("Header \(indexPath.row) : Status \(self.status[indexPath.row])")
cell.setStatus(isExpanded: self.status[indexPath.row])
return cell
}
}
extension ExpandableTableView: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.status[indexPath.row] = !self.status[indexPath.row]
tableView.reloadRows(at: [indexPath], with: .automatic)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
這是 UITableViewCell 的代碼
class DemoTableViewCell: UITableViewCell {
@IBOutlet private var lblHeader:UILabel!
@IBOutlet weak var imgIndicator: UIImageView!
@IBOutlet private var containerStackView:UIStackView!
func setHeader(_ header:String) {
self.lblHeader.text = header
}
func setStatus(isExpanded:Bool) {
self.containerStackView.isHidden = !isExpanded
if (isExpanded){
self.imgIndicator.transform = CGAffineTransform(rotationAngle: -.pi/2)
}else {
self.imgIndicator.transform = CGAffineTransform(rotationAngle: 0)
}
self.containerStackView.layoutIfNeeded()
}
}
任何幫助將不勝感激。
謝謝
編輯
代碼:
使用自動布局使用 UITableView 單元格示例更新 1
自定義表格視圖單元格
fileprivate class CustomCell: UITableViewCell
{
var imgIndicator: UIImageView!
static let tableViewCellIdentifier = "cell"
override init(style: UITableViewCell.CellStyle,
reuseIdentifier: String?)
{
super.init(style: style,
reuseIdentifier: reuseIdentifier)
configureIndicator()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
private func configureIndicator()
{
let config = UIImage.SymbolConfiguration(textStyle: .largeTitle)
let image = UIImage(systemName: "chevron.right.circle",
withConfiguration: config)
imgIndicator = UIImageView(image: image)
imgIndicator.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imgIndicator)
// auto-layout
imgIndicator.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
.isActive = true
imgIndicator.topAnchor.constraint(equalTo: contentView.topAnchor)
.isActive = true
imgIndicator.widthAnchor.constraint(equalTo: imgIndicator.heightAnchor,
multiplier: 1).isActive = true
imgIndicator.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
.isActive = true
}
// Simplified just to do the animation
// Customize with your logic
func setStatus(isExpanded: Bool)
{
if isExpanded
{
imgIndicator.transform = CGAffineTransform(rotationAngle: .pi/2)
}
}
}
基本視圖控制器配置
class TableViewAnimationVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
// This is just view set up, you can ignore this
title = "Animation rotation"
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.backgroundColor = .white
navigationController?.navigationBar.tintColor = .white
view.backgroundColor = .white
configureTableView()
}
private func configureTableView()
{
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(CustomCell.self,
forCellReuseIdentifier: CustomCell.tableViewCellIdentifier)
tableView.dataSource = self
tableView.delegate = self
// remove additional rows
tableView.tableFooterView = UIView()
view.addSubview(tableView)
// Auto layout
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
.isActive = true
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
.isActive = true
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
.isActive = true
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
.isActive = true
}
}
表視圖資料源
extension TableViewAnimationVC: UITableViewDataSource
{
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
// random number
return 10
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell =
tableView.dequeueReusableCell(withIdentifier: CustomCell.tableViewCellIdentifier)
as! CustomCell
cell.textLabel?.text = "Tap to rotate"
return cell
}
}
表視圖委托
extension TableViewAnimationVC: UITableViewDelegate
{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
// Retrieved the actual cell that was tapped
let cell = tableView.cellForRow(at: indexPath) as! CustomCell
// Perform animation in block
UIView.animate(withDuration: 2.0) {
cell.setStatus(isExpanded: true)
} completion: { (success) in
if success
{
// do your processing after the animation has completed
}
}
}
}
最后結果:

使用 OP 代碼示例更新 2
問題似乎在于使用相同的影片塊來重新加載表格視圖并執行其他 UIView 影片。
我看到的選項是將這兩個影片分開。
一種選擇是完成旋轉影片,然后重新加載您的 tableview 行以進行擴展 - 您可以對此進行試驗。
我將向您展示第二個選項,這似乎是一個更好的用戶體驗。在高水平:
- 找出當前應該為哪個單元格設定影片
- 用影片重新加載表格視圖行
- 在單獨的 UIView 影片塊中,執行其他影片
以下是我為實作上述目標所做的更改:
首先,在你的單元格中
class DemoTableViewCell: UITableViewCell {
@IBOutlet private var lblHeader:UILabel!
@IBOutlet weak var imgIndicator: UIImageView!
@IBOutlet private var containerStackView:UIStackView!
// No change
func setHeader(_ header:String) {
self.lblHeader.text = header
}
// Contract / expand the table view cell only
func setStatus(isExpanded:Bool) {
self.containerStackView.isHidden = !isExpanded
self.containerStackView.layoutIfNeeded()
}
// Animate the indicator separately
func animateIndicator()
{
var endAngle: CGFloat = .pi/2.0
var startAngle = CGFloat.zero
if self.containerStackView.isHidden
{
startAngle = .pi/2
endAngle = .zero
}
imgIndicator.transform
= CGAffineTransform(rotationAngle: startAngle)
UIView.animate(withDuration: 0.5) { [weak self] in
self?.imgIndicator.transform
= CGAffineTransform(rotationAngle: endAngle)
}
completion: { (success) in
// do anything
}
}
}
在ExpandableTableView我做了一些改變:
// Unchanged, done by you
var status:[Bool] = [Bool].init(repeating: false, count: 10)
// Stores the current cell's index path which should be animated
// This is for my convenience as I couldn't grasp your complete logic
// you can edit based on your logic
var shouldAnimate: [IndexPath] = []
UITableViewDelegate 的變化
extension ExpandableTableView: UITableViewDelegate {
func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
self.status[indexPath.row] = !self.status[indexPath.row]
// Added by me to keep track of which cell to animate
shouldAnimate.append(indexPath)
tableView.reloadRows(at: [indexPath], with: .fade)
}
// Perform your UIView animations in here
func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath)
{
if let cell = cell as? DemoTableViewCell,
shouldAnimate.firstIndex(of: indexPath) != nil
{
cell.animateIndicator()
}
}
// Unchanged
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
結果接近我認為您希望實作的結果:

調整時間以嘗試使展開和旋轉影片更好地同步。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/427939.html
