Offset HeaderView in Tableview to display like cards - ios

I am currently trying to offset HeaderView for UITableView to get some feel of passbook view but doesn't need to behave like a passbook, just that the upper view gets offset certain pixels to overlay the sections.
Below are a couple of examples I have been working on.
If you notice the first picture, the layout is completed customized in CollectionView, however, I feel like it's over-engineered to get the feel of something based on UITableView in UICollectionView. However the context of the output needs to be rendered just like the one in UITableView based on the second picture, but I am curious if there is any way to offset the "y" value to overlap the previous section header in UITableView?

You need to use a custom UICollectionViewLayout.
Basically, use a UICollectionView with vertical scroll, set the items width equal to the screen's width and implement a custom UICollectionViewLayout instead using UICollectionViewFlowLayout.
You can't overlap two cells in UITableView, because doesn't exist the concept of layout. Cells in UITableView are sequentially.
Here a possibile library.

as #Fry mentioned in his answer, UITableView not really expect you to "move" the section header or cell, and UICollectionView maybe a better option as it give a high degree of flexibility (but of course you will need some work to implement a custom UICollectionViewLayout).
But if you insist to use UITableView, here is a simple idea to achieve what you asked for. Just set the backgroundColor of the section header of next section to match the previous section. This really just give you the "feel" of passbook view but not behave like it.
For example,
let mockData = [(key: "section 1", value: [], color: UIColor.red),
(key: "section 2", value: [], color: UIColor.blue),
(key: "section 3", value: [3, 4, 5], color: UIColor.green)]
...
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as! TestViewHeader
header.containerBackground.backgroundColor = mockData[section].color
// here .white is just an example, you can add any color you want to match with the background or the navigationBar, depends on your design
header.contentView.backgroundColor = (section == 0) ? .white : mockData[section - 1].color
header.containerLabel.text = mockData[section].key
header.containerBackground.roundCorners(corners: [.topLeft, .topRight])
return header
}
And here is the result:
also attached my tableView Header and my helper function for your reference:

Related

Swift Dynamically growing a cell depending on the text length

I have a TableViewController which contains 2 sections:
Section 1 - is a cell which is loaded from a xib file. This cell just contains a TextView.
Section 2 - Contains multiple cells populated from an Array.
The section 1 only exists if the master (previous) UITableView cell you select contains a certain piece of data.
All of the above works as expected, below is the parent view. The list of items come from a database, some items have a description, and some do not. For example below this image, you'll see the view is 'Classic Starters' is selected. Then below that, you'll see the view if 'Stir Frys' is selected. Stri Frys contains a description:
Now, what I want is, the description cell which is shows on the Stir Frys page, to automatically grow depending on the length of the text inside it. So if a description is 10 lines long, it will grow to show all 10 lines.
Does this have to be done programmatically, or is their a feature in XCode I'm missing ?
You can use UITableViewAutomaticDimension.
1)
Set properties estimatedRowHeight and rowHeight of your tableview, in viewDidLoad for example. Like this :
self.tableView.estimatedRowHeight = 50
self.tableView.rowHeight = UITableViewAutomaticDimension
2) Return UITableViewAutomaticDimension in your heightForRowAt delegate method :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
First you need to do is to set estimatedRowSize to a value that best estimates most common size, and rowSize to UITableViewAutomaticDimension:
self.tableView.estimatedRowHeight = 44
self.tableView.rowHeight = UITableViewAutomaticDimension
In your case, since except the first one all the other cells are supposed to be the same, you can use the height of the rest of the cells as the estimatedRowHeight.
You don't have to implement heightForRowAt at all.
The second step you need to do is to setup proper constraints on the cells. That means you have to constrain the contents of the cell to the left, right, top and bottom of the cell, so that when contents grow, the cell will need to grow, too. Common mistake is to forget to constrain bottom, so then the cell does not grow and the contents leak through the bottom of the cell.
Third, since your dynamic cell contains UITextView, you need to make sure that it will grow with its text. That is not automatic. To achieve that, based on this answer, this should suffice (in the cell):
textView.isScrollEnabled = false
If you are using storyboard, just uncheck scroll enabled.

Can I use a tableviewcontroller and the prototype cells to split the screen into three sections?

I want to split my ViewController into three equal sections eg. "What", "Why", "Where" and when each view is tapped it goes to a se. I thought about using a UIViewController and having three separate views and then using a tap gesture with each view that takes to an appropriate page.
But then I thought maybe I could use a master-detail tableviewcontroller and an array of three strings to populate each cell.
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
I don't know which way is more legitimate and with the tableviewcontroller my main issue is cell height. Because there is only one cell in each section ideally i'd like the cell height to take up the full height of the section but not sure if i can set cell height to 100% for example.
Thank.
If you really just want 3 equally sized sections and you're building for >= iOS9, the easiest and fastest way would be to just use a vertical UIStackView.
Just set it's alignment to fill and its distribution to fill equally, drop in 3 UIButtons. Give you're stackView's topAnchor, bottomAnchor, leadingAnchor and trailingAnchor a constraint of 0 to the superview.
Of course you can use a UITableView, but it would be quite a lot of work to make sure, that your cells have a third of the screen size each. You would have to ensure that they adapt dynamically based on the screen size (which totally is possible). Also if you use a tableView, for something like this a static one is best. Then you don't have to implement a lot of the delegate methods like cellForRow etc.

How to I build a continuous parallax scroll/Collection view?

I am looking to build a continuous parallax scroll like this.
http://www.screencast.com/t/7Z48zkkW
But my Requirement is view and then CollectionView like this
When collection view scroll then changes upper view height.
and yes upper view and collection view is separate.
I Have also navigation bar it also goes up when user scroll
You can use collectionView with section header for this effect. However, the effect collectionView bounced below the search can't be achieved by this way instead the whole view will bounce.
Simplest solution for iOS 9 +
1) Make a cell for items above the search
2) Make reusableView for search bar (section header)
3) Make cells for those pictures
i.e. you will have two cell's prototypes and one reusableView
In viewDidLoad of viewController with collectionView use following code so that header of section gets pinned always in top:
let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout // casting is required because UICollectionViewLayout doesn't offer header pin. Its feature of UICollectionViewFlowLayout
layout?.sectionHeadersPinToVisibleBounds = true
Number of section: Keep it 2
Number of row for section == 0 will be 1 which will be items above search
Number of row for section == 2 will be number of images you have
Now, in collection view datasource you have a method viewForSupplementaryElementOfKind which you need to implement to get sectionHeaderView.
implement referenceSizeForHeaderInSection function for hiding sectionHeader for first section (section == 0) by returning CGSize(width: 0, height: 0) and for second section (section == 1) return size of searchBar as you want.
in cellForItemAtIndexPath return cells according to section.
EDIT
I think you don't need sticky header at top like that search bar. So its better you use collectionView with section header. (section header contains the red View you marked)

Insert in a tableView set to Autoresize cause a scroll issue

I've an issue for few days and really I can't explain why it goes like that.
I'm doing a chat, set up with a tableView, printing message into cell. These cells are designed with prototypes, there are 3 different type (but anyway it doesn't matter). Text is typed, message is send, cell is inserted in table and then we scroll to the bottom of the tableView.
As you know, in a chat view the container of the message has to fit this text (which is a view), and then the cell has to fit to this container (Label in orange, container in purple).
This container has a variable height and grow along the text, changing cell height.
I've set many constraint for auto-layout display but I didn't have different cell height than the height I initially set for it in the project (no adaptative behaviour). Chat Message were cut.
So, I've tried to set each rowHeight by myself using the method heightForRowAtIndexPath, calculating constraint along text size but it create a real bad behaviour (changing cells when scrolling for example). The size was often wrong calculated/recalculated.
That's why I'm finally using estimatedRowHeight set to 44 combine with UITableViewAutomaticDimension. Here it does the trick ! Waouh ! But it's not as good as expected..
When the table view appears all is good. Containers fit to their label, rows' height fit to their container and it's beautiful. The problem appears during an insert.
After many tests, I notice that this bad behaviour only appears when multilines label remains in the table view.
During an insert, each cell seems to resize to 44 before adapt its height to content, and then create a gap compared to previous state which create a strange scroll of the table view :
If I change the estimatedRowHeight it made this worst.
I can show my code if you want, but I don't think it will be very useful here because I'm not using complicated function.. only insert, automatic height for cells and scroll down which are functions delegate for tableView.
Can you help me please ? Really I don't know how to change that.. every chat application does the trick but I can't found out the way.
Thank you for answer, excuse my english level I'm a poor french student..
If you need some code comment I'll give it.
I think you can cache height value for every cell in cellForRowAtIndex method and in HeightForRowAtIndex set the corresponding height for that cell.
You can just do this way :
var cellCached = Dictionary<Int,AnyObject>()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
table.rowHeight = yourCell.yourLabel.frame.origin.y + yourCell.yourLabel.frame.height + 10
cellCached[indexPath.row] = yourTable.rowHeight
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(tableView == yourTable)
{
if(cellCached[indexPath.row] != nil)
{
return cellCached[indexPath.row] as! CGFloat
}
else
{
return 200
}
}
else
{
return UITableViewAutomaticDimension
}
}

Conditionally hiding cell separators and removing hidden section space Swift

I want cell separators in every single one of my sections other than section 0.
Between "New Game", "Friends", "Random", "Judge", and "Challenges" I don't want any separators. The cell type in section "0" or "New Game" is different than the other sections' cell types so I tried this: iOS swift remove UITableView Cell separator space but it didn't work.
Another issue I'm facing is how to erase the space left when a header is gone because it has no rows in it.
Here is a picture:
As you can see, "Waiting For Opponent" has disappeared because there are no rows in the section.
So to be extremely clear:
How do I conditionally hide the separators in section 0 without hiding the entire tableView's separators?
How do I hide the space that is created when I hide a section header?
I can think of two options:
Hide the separators entirely and implement your own separator by adding a UIView with 1-2pt height placed at the bottom of the cell which can then be hidden/unhidden based on your requirements in cellForRowAtIndexPath. OR
In cellForRowAtIndexPath, change the insets of the separator for that cell so that the separator goes out of the view. Eg:
cell.separatorInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, cell.bounds.size.width-cell.layoutMargins.left)
Have you tried returning zero in tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat ??

Resources