简体   繁体   中英

Swift - How to programmatically rotate a UIImageView in UITableViewHeader

I have built a UITableView with collapsable sections and with the code I have written I can manage to change the title of the button in the header. Then I decided that I want a rotating arrow in a UIImageView on the right, so I built it.

Here's how I built the interface:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    // Create a UIView with title and button inside
    let myView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 36))
    myView.backgroundColor = .red

    let button = UIButton(type: .system)
    button.addTarget(self, action: #selector(openClose), for: .touchUpInside)
    button.tag = section
    button.translatesAutoresizingMaskIntoConstraints = false

    let myImageVIew: UIImageView = {
       let iv = UIImageView()
        iv.image = UIImage(named: "HeaderImage")
        iv.translatesAutoresizingMaskIntoConstraints = false
        return iv
    }()

    myView.addSubview(myImageVIew)
    myImageVIew.rightAnchor.constraint(equalTo: myView.rightAnchor).isActive = true
    myImageVIew.centerYAnchor.constraint(equalTo: myView.centerYAnchor).isActive = true
    myImageVIew.heightAnchor.constraint(equalTo: myView.heightAnchor).isActive = true
    myImageVIew.widthAnchor.constraint(equalTo: myView.heightAnchor).isActive = true

    myView.addSubview(button)
    button.centerYAnchor.constraint(equalTo: myView.centerYAnchor).isActive = true
    button.rightAnchor.constraint(equalTo: myView.rightAnchor).isActive = true
    button.widthAnchor.constraint(equalTo: myView.widthAnchor).isActive = true
    button.heightAnchor.constraint(equalTo: myView.heightAnchor).isActive = true

    return myView
}

And here's how I open/close the sections:

@objc
private func openClose(button: UIButton) {
    let section = button.tag
    var indexPaths = [IndexPath]()
    for row in storedData[section].names.indices {
        let indexPath = IndexPath(row: row, section: section)
        indexPaths.append(indexPath)
    }

    let isExpanded = storedData[section].isExpanded
    storedData[section].isExpanded = !isExpanded

    if isExpanded {
        // Here the code to rotate the image
    } else {
        // Here the code to rotate the image
    }

    if !isExpanded {
        tableView.insertRows(at: indexPaths, with: .fade)
    } else {
        tableView.deleteRows(at: indexPaths, with: .fade)
    }
}

Is there a way to access the UIImageView from the openClose() function? If there isn't, how can I correct this code?

Also here's the struct that allows everything to work:

struct ExpandableNames {
var isExpanded: Bool
let names: [String]
}

Thank you.

A clean approach would be to subclass the UIView (you also might want to look into UITableViewHeaderFooterView which is reusable if you have performance problems). Then use layout driven UI animations - see https://developer.apple.com/videos/play/wwdc2018/233/

To access the header view from your openClose action, you could query the delegate method tableView(_:viewForHeaderInSection:). You can probably structure this better a bit later, using the tag property doesn't seem very scalable, but you can refactor a little later.

Here's how I managed to do it: I added into my openClose() function this code.

    let section = sender.tag
    let subs = sender.superview?.subviews

    let image = subs?[0] as! UIImageView
    image.image = UIImage(named: "HeaderImage")

This allows me to rotate the Image with a normal CGAffineTransform.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM