Use UICollectionViews to create dynamic and multip

2019-06-08 02:36发布

问题:

I'm interested in creating a view that contains multiple features that users can scroll down and see i.e. pictures, description, comments, carousels etc. I am aware that the UICollectionView is able to provide this type of layout. I initially thought UITableViews would be the best approach.

I have looked at several tutorials and GitHub repos but majority of them just use a UICollectionView in a standard grid layout. I've also looked at IGListKit used by Instagram and some the tutorials linked to it.

I'm aiming to get something like the KitchenStories app:

I was wondering if someone could advice me in terms of the direction and approach best for this.

回答1:

Don't try to do too much with any single view, even a UICollectionView.

The screen you've shown has a UITabBarController manage its top-level arrangement. The currently selected tab (“Home”) has a UINavigationController managing its content.

On the top of the navigation stack is, probably, a collection view or a table view. Either could be used here because the elements are visually laid out as screen-width rows in a stack. A table view is simpler because then you don't have to worry about setting up the layout.

The table view has several visible rows, each different:

  • The title/image row (“Easy seafood paella”)
  • The ratings row
  • The export row (hearts / save / share)
  • The comments row
  • The creator row (I assume, since it looks like it's probably a headshot and a name)

And there are probably even more unique rows out of view.

In your storyboard, you can design each of these rows as a prototype row in the table view controller's scene. Or you can design the table view with static content rows, which is easier if you won't need to change the order of the rows or duplicate any rows at run time.

“But Rob,” you say, “I can't fit all those rows into the table view in my storyboard!” Make the storyboard scene taller. UIKit will resize it at run time to fit the device screen.

In each row, drag in and arrange whatever subviews you need for that row's data. For example, the title/image row needs a UIImageView and a UILabel. The ratings row needs a label, probably a custom view to display and edit the stars, and perhaps a stack view for layout.

For each row, you'll need a separate subclass of UITableViewCell with outlets to that row's views. To pass the data to each cell for display, make each cell conform to a protocol:

protocol RecipeUsing {
    var recipe: Recipe? { get set }
}

Then, in your table view controller, you set it like this if you're using static content:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAt: indexPath)
        if let user = cell as? RecipeUsing {
            user.recipe = recipe
        }
        return cell
    }

You'll need a RecipeTitleImageCell with outlets to the UIImageView and UILabel. Something like this:

class RecipeTitleImageCell: UITableViewCell, RecipeUsing {

    @IBOutlet var label: UILabel!

    // UITableViewCell has an imageView property that's not an outlet