HeroTransitions / Hero

Elegant transition library for iOS & tvOS
https://HeroTransitions.github.io/Hero/
MIT License
22.06k stars 1.73k forks source link

Transition between collectionView and tableView #646

Closed yankelandroid closed 2 years ago

yankelandroid commented 4 years ago

What did you do?

I set the hero identifier into collectionviewcell and the same into the stretchy header that i added in the tableview (GSKStretchyHeaderView)

What did you expect to happen?

transition between the image

What happened instead?

nothing

General Information

JoeMatt commented 4 years ago

A code sample would be very helpful here. We need to see what the view's super class types are especially.

yankelandroid commented 4 years ago

This is the first controller : import UIKit import BarcodeScanner

class CatalogFiltersVC: UIViewController {

@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var filtersCollection: UICollectionView!
@IBOutlet weak var selectedFiltersCollection: UICollectionView!
@IBOutlet weak var productsCollection: UICollectionView!

var filters:[String] = ["Color", "Size", "Season", "Price", "Material", "Line"]
var selectedFilters:[String] = ["Oxfords and Derbies", "Oxfords", "Derbies"]

override func viewDidLoad() {
    super.viewDidLoad()

    setSearchBar()
    filtersCollection.register(UINib(nibName: FilterCell.identifier, bundle: nil), forCellWithReuseIdentifier: FilterCell.identifier)
    selectedFiltersCollection.register(UINib(nibName: SelectedFilterCell.identifier, bundle: nil), forCellWithReuseIdentifier: SelectedFilterCell.identifier)
    productsCollection.register(UINib(nibName: ProductCell.reuseIdentifier, bundle: nil), forCellWithReuseIdentifier: ProductCell.reuseIdentifier)

}

func setSearchBar() {
    self.searchBar.showsBookmarkButton = true
    self.searchBar.layer.borderWidth = 1
    self.searchBar.layer.borderColor = #colorLiteral(red: 0.8509803922, green: 0.8509803922, blue: 0.8549019608, alpha: 1)
    self.searchBar.setImage(UIImage(named: "barcode"), for: .bookmark, state: .normal)
}

@IBAction func showAllFilters(_ sender: Any) {
    performSegue(withIdentifier: "filter", sender: "All")
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let nextVC = segue.destination as? FilterContainerVC, let s = sender as? String {
        if s == "All"{
            nextVC.rootVC = UIStoryboard(name: "Catalog", bundle: Bundle.main).instantiateViewController(withIdentifier: "AllFiltersVC")
        }else {
            switch s {
            case "Color":
                nextVC.filterType = .color
            case "Size":
                nextVC.filterType = .size
            default:
                nextVC.filterType = .other
            }
            nextVC.rootVC = UIStoryboard(name: "Catalog", bundle: Bundle.main).instantiateViewController(withIdentifier: "FilterVC")
        }

    }
}

}

extension CatalogFiltersVC : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { switch collectionView { case filtersCollection: return filters.count case selectedFiltersCollection: return selectedFilters.count case productsCollection: return 150 default: return 0 } }

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    switch collectionView {
    case filtersCollection:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FilterCell.identifier, for: indexPath) as! FilterCell
        cell.filterLbl.text = filters[indexPath.row]
        return cell
    case selectedFiltersCollection:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SelectedFilterCell.identifier, for: indexPath) as! SelectedFilterCell
        cell.nameLbl.text = selectedFilters[indexPath.row]
        return cell
    case productsCollection:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ProductCell.reuseIdentifier, for: indexPath) as! ProductCell
        cell.delegate = self
        return cell
    default:
        return UICollectionViewCell()
    }

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    switch collectionView {
    case filtersCollection:
        let height: CGFloat = 38
        let addedWidth: CGFloat = 45
        let textWidth = filters[indexPath.row].localized().size(withAttributes: [
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0)]).width
        return CGSize(width: textWidth + addedWidth, height: height)
    case selectedFiltersCollection:
        let height: CGFloat = 32
        let addedWidth: CGFloat = 55
        let textWidth = selectedFilters[indexPath.row].localized().size(withAttributes: [
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0)]).width
        return CGSize(width: textWidth + addedWidth, height: height)
    case productsCollection:
        return CGSize(width: (view.bounds.width - 32 - 15)/2, height: 236)
    default:
        return CGSize.zero
    }

}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    switch collectionView {
    case filtersCollection:
        self.performSegue(withIdentifier: "filter", sender: filters[indexPath.row])
    case selectedFiltersCollection:
        selectedFilters.remove(at: indexPath.row)
        selectedFiltersCollection.reloadData()
    case productsCollection:
        self.performSegue(withIdentifier: "productDetail", sender: nil)
    default:
        return
    }
}

}

extension CatalogFiltersVC : UISearchBarDelegate {

func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {
    let controller = BarcodeScannerViewController()
    controller.codeDelegate = self
    controller.errorDelegate = self
    controller.dismissalDelegate = self
    controller.isOneTimeSearch = false

    present(controller, animated: true, completion: nil)
}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    self.searchBar.setShowsCancelButton(true, animated: true)
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchBar.resignFirstResponder()
    searchBar.setShowsCancelButton(false, animated: true)
}

}

extension CatalogFiltersVC: BarcodeScannerCodeDelegate {

func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
    print(code)

    controller.reset()
    controller.dismiss(animated: true, completion: nil)
}

}

extension CatalogFiltersVC: BarcodeScannerErrorDelegate { func scanner( controller: BarcodeScannerViewController, didReceiveError error: Error) { print(error) } } extension CatalogFiltersVC: BarcodeScannerDismissalDelegate { func scannerDidDismiss( controller: BarcodeScannerViewController) { controller.dismiss(animated: true, completion: nil) } }

extension CatalogFiltersVC : ProductDelegate { func likeClicked(isLiked: Bool) {

}

}

yankelandroid commented 4 years ago

This is the cell of the collectionview : import UIKit import Hero

protocol ProductDelegate { func likeClicked(isLiked:Bool) }

class ProductCell: UICollectionViewCell {

var delegate : ProductDelegate?
var isLiked = true

static let reuseIdentifier = String(describing: ProductCell.self)

@IBOutlet weak var likeImg: UIButton!
@IBOutlet weak var productImg: UIImageView!
@IBOutlet weak var colorView: RoundedView!
@IBOutlet weak var colorLbl: UILabel!
@IBOutlet weak var reductionLbl: UILabel!
@IBOutlet weak var productNameLbl: UILabel!
@IBOutlet weak var priceLbl: UILabel!
@IBOutlet weak var stockLbl: UILabel!

override func awakeFromNib() {
    productImg.hero.id = "produtImage"
}

@IBAction func likeClicked(_ sender: Any) {
    isLiked = !isLiked
    UIView.transition(with: self.likeImg, duration: 0.2, options: .transitionCrossDissolve, animations: {
        if self.isLiked {
             self.likeImg.setImage(UIImage(named: "likeOn"), for: .normal)
        }else {
             self.likeImg.setImage(UIImage(named: "likeOff"), for: .normal)
        }

    }, completion: nil)
    delegate?.likeClicked(isLiked: false)
}

}

yankelandroid commented 4 years ago

This is the second controller : import UIKit import GSKStretchyHeaderView

class ProductDetailVC: UIViewController {

@IBOutlet weak var tableview: UITableView!

var customStretchFactor: CGFloat = 0.0
var header : ProductDetailHeaderView?
let MAX_HEADER_HEIGHT = CGFloat(441)
let MIN_HEADER_HEIGHT = CGFloat(80)

override func viewDidLoad() {
    super.viewDidLoad()

    setupHeader()

    setupTableView()

}

func setupHeader(){

    header = ProductDetailHeaderView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: MAX_HEADER_HEIGHT))

    header!.minimumContentHeight = MIN_HEADER_HEIGHT
    header!.maximumContentHeight = MAX_HEADER_HEIGHT

    header!.contentAnchor = .top
    header!.contentShrinks = true
    header!.contentExpands = false
    header!.stretchDelegate = self
    tableview.addSubview(header!)
}

func setupTableView() {
    tableview.register(UINib(nibName: DetailColorCell.reuseIdentifier, bundle: nil), forCellReuseIdentifier: DetailColorCell.reuseIdentifier)
}

@IBAction func close(_ sender: Any) {
    dismiss(animated: true, completion: nil)
}

@IBAction func share(_ sender: Any) {

}

}

extension ProductDetailVC : UITableViewDelegate, UITableViewDataSource {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 100
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: DetailColorCell.reuseIdentifier, for: indexPath)
        cell.selectionStyle = .none
        return cell
    }else {
        return UITableViewCell()
    }
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.row == 0 {
        return CGFloat(152)
    }else {
        return CGFloat(20)
    }
}

}

extension ProductDetailVC : GSKStretchyHeaderViewStretchDelegate {

func stretchyHeaderView(_ headerView: GSKStretchyHeaderView, didChangeStretchFactor stretchFactor: CGFloat) {

    if customStretchFactor == 0.0 && stretchFactor != 1{
        customStretchFactor = stretchFactor
    }

    var currentfactor: CGFloat = 1.0
    if customStretchFactor != 0 {
        currentfactor = stretchFactor/customStretchFactor
    }

    header?.buttonStack.alpha = min(1, currentfactor)
    header?.promoLbl.alpha = min(1, currentfactor)
    header?.SKULbl.alpha = min(1, currentfactor)
    header?.productImageWidth.constant = 200 - 130 * ( 1 - min(1, currentfactor) )
    header?.productImageTop.constant = 44 - 39 * ( 1 - min(1, currentfactor) )
    header?.productImageX.constant = (0 - 129 * ( 1 - min(1, currentfactor) ) )
    header?.nameTop.constant = 252 - 242 * ( 1 - min(1, currentfactor) )
    header?.nameLeading.constant = 80 * ( 1 - min(1, currentfactor) )
    header?.priceLeading.constant = 80 * ( 1 - min(1, currentfactor) )

    let nameSize = 24 - 7 * ( 1 - min(1, currentfactor) )
    header?.nameLbl.font = UIFont.systemFont(ofSize: nameSize, weight: .semibold)
    let priceSize = 17 - 7 * ( 1 - min(1, currentfactor) )
    header?.priceLbl.font = UIFont.systemFont(ofSize: priceSize, weight: .medium)
    header?.priceTop.constant = 15.5 - 10 * ( 1 - min(1, currentfactor) )

}

}

yankelandroid commented 4 years ago

the headerview of the tableview : import UIKit import GSKStretchyHeaderView import Hero

class ProductDetailHeaderView: GSKStretchyHeaderView {

let xibName = String(describing: ProductDetailHeaderView.self)

@IBOutlet weak var promoLbl: UILabel!
@IBOutlet weak var buttonStack: UIStackView!
@IBOutlet weak var SKULbl: UILabel!
@IBOutlet weak var priceLbl: UILabel!
@IBOutlet weak var nameLbl: UILabel!
@IBOutlet weak var productImg: UIImageView!

@IBOutlet weak var productImageWidth: NSLayoutConstraint!
@IBOutlet weak var productImageTop: NSLayoutConstraint!
@IBOutlet weak var productImageX: NSLayoutConstraint!
@IBOutlet weak var nameTop: NSLayoutConstraint!
@IBOutlet weak var nameLeading: NSLayoutConstraint!
@IBOutlet weak var nameTrailing: NSLayoutConstraint!
@IBOutlet weak var priceTop: NSLayoutConstraint!
@IBOutlet weak var priceLeading: NSLayoutConstraint!

var view: UIView!

override init(frame: CGRect) {
    super.init(frame: frame)
    initialSetup()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    initialSetup()
}

func initialSetup() {
    xibSetup()
    layer.masksToBounds = false
}

fileprivate func xibSetup() {
    view = loadViewFromNib()

    // use bounds not frame or it'll be offset
    view.frame = bounds

    // Make the view stretch with containing view
    view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]

    productImg.hero.id = "productImage"

    self.hero.isEnabled = true
    // Adding custom subview on top of our view (over any custom drawing > see note below)
    addSubview(view)

}

fileprivate func loadViewFromNib() -> UIView {
    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
    return nib.instantiate(withOwner: self, options: nil)[0] as! UIView
}

@IBAction func addToMyFavorite(_ sender: Any) {

}

@IBAction func addToWhisList(_ sender: Any) {
}

}

yankelandroid commented 4 years ago

I want to make the transition between the two imageviews

furysheep commented 4 years ago

@yankelandroid did you solve this issue?

yankelandroid commented 4 years ago

No

Le ven. 27 mars 2020 à 01:38, furysheep notifications@github.com a écrit :

@yankelandroid https://github.com/yankelandroid did you solve this issue?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/HeroTransitions/Hero/issues/646#issuecomment-604740842, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHPP7BBQRP3YKU3P6UMUA4TRJPRPHANCNFSM4JRAEPGA .