ra1028/Carbon

How to show hide Section with UICollectionView?

arimunandar opened this issue · 6 comments

i'm trying to show hide section with UICollectionView, but every rendering component its like ugly animation, how to implement show hide with UICollectionView?

Thanks for helping :)

Hi @arimunandar ,

Can you take me a sample code?
It depends on the case but when you call render again like below, it should hide with animation.

// call on main thread
renderer.render(
    Section(
        id: "id value"
        header: ViewNode(Sample()),
        cells: [
            CellNode(Sample()),
            CellNode(Sample())
        ]
        footer: ViewNode(Sample()),
    )
)

// ↓↓↓ Call again to hide Section ↓↓↓

renderer.render()  // renderer.data = [],  renderer.render([])

Moreover, you can handle show or hide section using Bool flag as state.

var hidesSection: Bool = false {
    didSet { render() }
}

func render() {
    renderer.render(
        hidesSection ? nil : Section(
            id: "id value"
            header: ViewNode(Sample()),
            cells: [
                CellNode(Sample()),
                CellNode(Sample())
            ]
            footer: ViewNode(Sample()),
        )
    )
}

And, Example app may be helps you!

Hi @ra1028 , thanks for your answer,

I have done it according to the example above, but when the components in hide always scroll back to the top.

this is my code example:

var isHide: Bool = true {
    didSet { render() }
}

 override func viewDidLoad() {
        super.viewDidLoad()

        title = "Kyoto"
        collectionView?.collectionViewLayout = layout
        collectionView.contentInset.bottom = 24
        renderer.updater.alwaysRenderVisibleComponents = false
        renderer.updater.skipReloadComponents = false
        render()
}

func render() {
        renderer.render(
            Section(
                id: ID.top,
                header: ViewNode(KyotoTop())
            ),
            Section(
                id: ID.gallery,
                header: ViewNode(Header(title: "PHOTOS")),
                cells: photo.enumerated().map({ _, data in
                    CellNode(KyotoImage(title: data.name, image: data.image, onSelected: {
                        self.isHide = false
                    }) {
                        self.isHide = true
                    })
                }),
                footer: !isHide ? nil : ViewNode(KyotoLicense {
                    let url = URL(string: "https://unsplash.com/")!
                    UIApplication.shared.open(url)
                })
            )
        )
    }

there is something wrong with my code?
I just want, when the footer in hide doesn't scroll back up again.

thnks :)

@arimunandar
Do you indicate that content size becomes smaller when the element hides?
Since it is the correct behavior of UIKit, it's a good idea to display an empty component as a placeholder.

struct EmptyComponent: Component, Equatable {
    var height: CGFloat

    func renderContent() -> UIView {
        return UIView()
    }

    func render(in view: UIView) {}

    func referenceSize(in bounds: CGRect) -> CGSize? {
        return CGSize(width: bounds.width, height: height)
    }
}
footer: !isHide ? ViewNode(EmptyComponent(height: placeholderHeight)) : ViewNode(KyotoLicense {
    let url = URL(string: "https://unsplash.com/")!
    UIApplication.shared.open(url)
})

Hi @ra1028 ,

I have done it according to the example above, but when the components in hide still scroll back to the top.

this my Sample video Sample

Thnks. 😄

@arimunandar

I understood.
That is because it becomes reload of the entire section.

In UIKit, to change the header or footer we should to reload section.
Please try to separate the section that has the footer you want to hide/show.

var isHide: Bool = true {
    didSet { render() }
}

 override func viewDidLoad() {
        super.viewDidLoad()

        title = "Kyoto"
        collectionView?.collectionViewLayout = layout
        collectionView.contentInset.bottom = 24
        renderer.updater.alwaysRenderVisibleComponents = false  // It's default.
        renderer.updater.skipReloadComponents = false  // It's default.
        render()
}

func render() {
        renderer.render(
            Section(
                id: ID.top,
                header: ViewNode(KyotoTop())
            ),
            Section(
                id: ID.gallery,
                header: ViewNode(Header(title: "PHOTOS")),
                cells: photo.enumerated().map({ _, data in
                    CellNode(KyotoImage(title: data.name, image: data.image, onSelected: {
                        self.isHide = false  // You should `weak self`.
                    }) {
                        self.isHide = true
                    })
                })  
            ),
            Section(
                id: ID.footer,
                footer: !isHide ? nil : ViewNode(KyotoLicense {
                    let url = URL(string: "https://unsplash.com/")!
                    UIApplication.shared.open(url)
                })
        )
    }

Did you solve this?
I close this issue.
If you still want to ask, please reopen it.