I'm trying to structure a page similar to Twitter's profile page. It looks like they are using a basic UITableView. The top profile is just the tableHeaderView. The tabs are a UISegmentedControl inside the SectionRowHeader so that it sticks to the top when scrolled. And the tweets are just the cells inside that section. And if you switch tabs, it seems like they are simply changing the underlying data and reloading the table.
However if you play with the page, you'll notice that changing tabs keeps the previous scroll position. And if you scroll back to the top on one tab, then of course the other tab has to be scrolled to the top otherwise it'll be scrolled underneath the header. Also, if you look closely the bottom part (the tweets) has its own scrollbar once you start scrolling. So it seems like that is its own tableview. So would that be a new tableview inside the cell of the main page? And if that's what they're doing, then the scrolling is seamless between them. You're able to scroll the bottom part up and only once the tabs are pinned to the top do the tweets scroll underneath it.
I'm trying to build a similar structured page but keep running into issues. Ideally I would also like to have the logic of those sub tabs broken out into separate view controllers for reuse but at this point I would just like to get this working.
Anyone have any idea of the structure they're using to setup a page like this?
I'm 99% certain they are simply adjusting the scroll indicator insets as you scroll view the table:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat const visibleHeaderHeight = 0.0; // your logic here
UIEdgeInsets const insets = UIEdgeInsetsMake(visibleHeaderHeight, 0.0, 0.0, 0.0);
self.scrollView. scrollIndicatorInsets = insets;
}
Also I'm pretty sure they are using a grouped style table view due to the sectioning, so you would need to build the sticky header yourself. You can also do that in -scrollViewDidScroll: though.
If you want to break the tabs into separate view controllers, I would recommend the following setup:
have a container view controller managing the header view containing the tabs
use UIViewController containment to plug in the active view controller
subscribe to the active view controller's scroll view's contentOffset and adjust the scroll indicator inset and sticky header y position accordingly
I tried to explain a bit here.
After a long long investigation that is how i achieve the twitter
profile behaviour.
UnderlayScrollView
MasterScrollView
Header ViewController
Bottom ViewController
PagerTabItems [CollectionView]
UIPagerController or any other horizontal scroll (Parchment, XLPagerTabStrip).
UnderlayScrollView is responsible of controlling the scroll gesture.
its contentoffset is used to adjust inner scroll contentOffsets.
Contentsize of the underlaying scroll is same as the masterscroll's
contentsize.
See the source code on github for more.
click
Related
I have a UIPageViewController in which each of the child view controller contains a WKWebview.
The content of WebView is structured in two parts:
The top part contains a fixed size header in a div.
The bottom part contains the content, that can be larger than the device.
You can see a representation in the following drawing:
When the content is larger than the device, the user needs to scroll the content horizontally until the end of it in order for the UIPageViewController to start the swipe between two pages, and this is expected.
The problem is that the top part contains a fixed size header, and so if the user starts the scrolling in the header, it still need to scroll horizontally to the end of the content for the swipe to start. This is obviously not user friendly, and I am not sure how to solve this issue.
Do you have any suggestions about this?
You can try it something like:
Take two different UIPaginationViews, One for Header and one for
Contents.
Now, add these UIPaginationView's to ScrollView and enable vertical scrolling.
In delegate method, if the user scroll the page of Header
PaginationView then you can set the appropriate Index on the
Contents PaginationView. As the width of the Header is equal to the
width of the screen, so scrolling it to next page is smooth.
Now, when user scrolls on the bottom content and page get's
changed then you will have to set the index on the top pagination
view to match the contents pagination view.
In the scrollView, Allow only vertical scrolling. so, when you
scrolls it will scroll both the UIPaginations views.
it will need little experiments to get the desired behaviour and first thing you will have to do is to separate the HEADER AND CONTENT. if that is possible then you can try this approach.
Hope it helps.
I've been trying to replicate this effect for a couple days which was inspired by Tumblr.
I've previously asked questions on here with different approaches of the same problem but to no avail. I'm just curious as to how the engineers at Tumblr created a horizontal collection view, with two vertical collection views, and is able to scroll down without affecting the view above (without resetting the position of the view when you scroll vertically in a different tab).
Header Views
I tried this, but the header view was isolated and I had to scroll to the right to see the collectionView cells. This did not work.
Changing the topLayoutConstraint constant of my UIView (not cv header) with respect to the contentOffSet of the vertical collectionView.
This almost got the effect I wanted, except that when I scrolled horizontally, there was a huge gap between my collection view and if I scrolled in that new tab, the UIView would appear again because, again, topLayoutConstraint gets scrolled up depending on the contentOffSet of my vertical collectionView contentOffset.
Changing the position of the UICollectionView frame, and scrolling the super view up simultaneously with NSNotificationCenter.
Alas, this method did the same as method #2, except that the vertical collection view cells scrolled faster than the super view.
I ran out of options to make this work so I will show you in detail what's attempted to be replicated (also note the scroll bar on the right):
Note when I scroll down the first tab. I switch, and then scroll down further. Originally, as I've said, there would be a gap between the second main CV, and when I scrolled, the view would reposition as if were scrolling up again. On here, the view on top keeps going up. So I'm curious as to what method Tumblr engineers used to do this. UICollectionView inside UIScrollView? Other suggestions?
I believe there is no UICollectionView involved. It looks like UIPageViewController and each its page is a UITableView.
Perhaps the UIPageViewController sits in a UITableView as well - the header also moves up when you scroll. This main table has only one cell (and a header) which is occupied by the UIPageViewController.
Hope it helps.
I am trying to recreate a UIView I have seen in multiple apps, mainly Shazam. The top half of the screen has some interactive buttons, and the bottom half looks like a tableView with custom cells. When the bottom half is panned/swiped up, the tableView scrolls over the top half with velocity, much like a scroll view.
I have been researching this and experimenting for a couple days now. I have gotten close, but not quite there.
My last approach was a view that had a tableView inside it. When the view was panned, the view would move to wherever the finger moved it to, but then would not have any velocity afterwards. Also when the tableView was panned/swiped down, it wouldn't move the whole view down.
Before that I tried a scrollView that took up the whole length of the screen. That gave the desired effect, but the button wasn’t tappable, and you could scroll the view in the button area, which is undesired.
Does it utilize ScrollViews or is it using a tableView that acts much like a ScrollView somehow.
Here is the Shazam UI/UX I am looking to recreate:
The top portion has interactive buttons, and doesn’t scroll. The bottom half shows content and when scrolled, covers up the top portion.
Below is what I have tried so far: This one is the panning view, which sort of works, but doesn’t have velocity and the tableView doesn’t scroll the view back down.
Any thoughts on a direction I can take from here is greatly appreciated. I am using Swift.
Cheers
This sort of thing is perhaps best done with a collection view and a custom layout — you can have some items for which you set layout attributes absolute to the view, and others relative to the scroll content offset.
There's a great (if wandering) discussion of this and other techniques in the Advanced User Interfaces with Collection Views talk from WWDC 2014.
This is actually simple than it seems at first. Here's how you can achieve this:
Create a UIViewController (not a UITableViewController).
Add some buttons to the top area of the screen.
Add a table view spanning the entire view controller's view. Make sure the table view is on top of the buttons added in the previous step.
Configure the top cell of the table view to be transparent (by setting its background color to Clear). Set the background color on the table view to Clear as well. This way it won't obscure the elements at the top of the screen, unless the table is scrolled up.
Because your table view is now transparent, you'll need to explicitly set the background color on the table cells other than the top one.
Profit!
I'm having a hard time finding the best way to structure this design.
The top view has a minimum height and becomes sticky when it reaches this height. The bottom view hosts a paging controller with three views within. Each of these views hosts either a collection view or table view with vertical scrolling.
I'm really at a loss on how to approach this. Is the entire view scrollable and I should prevent scrolling on the second view until the top view has reached it's sticky height? Or are each of these views separate uitableviews and the pagingcontroller is just one cell? Should I even be using a pagingcontroller or should I use a scrollview with paging enabled? (the latter was a little rough interaction-wise)
Thank you!
Take a look at the Advanced User Interfaces using Collection View from WWDC this year. This view is very very very similar to the iTunes Connect app interface. The entire session video explains how they created that interface.
I used a similar method to this to create the keyboard in the Emojicate app.
I think what I'd do is actually fake the sticky header. So something like this...
Use only one collection view.
Create a "segmented data source" that contains three data sources. (See the video from WWDC about this)
When the segmented control is changed then update the collection view by changing its layout and (if you want) dataSource.
Make the entire top section a header on the collection view.
When the collection view scrolls past a certain point (when you want to sticky the header) then have a second view that is the compressed header and make it visible at the top of the screen. This is not attached to the collection view at all.
When the segmented control changes you can update the collection view by changing the "selected datasource". The datasource can also contain a UICollectionViewLayout that will update it.
Essentially, the tableview you are talking about is just a collection view where the cell width is equal to the screen width. i.e. fake a table view.
The sticky header isn't sticky at all. Just when it starts to go off screen you can put a fake header there instead.
It will require a duplicate (ish) view and some thinking about how to structure the data but I think this will be easier and less resource hungry than having multiple collection views and page controller and stuff.
If you want me to go through it in more detail let me know but it's a complex subject. Watch the video first.
I would make this part a navigation bar. Should be relatively easy. Just have to customize the back button with a barButtonItem and do a couple of labels in the titleView.
I would make the next part a Table View.
The tableView has 2 sections. The first section doesn't have a section header and the second section doesn't have any cells but just a section header.
First and only cell in this section:
And the rest would be the second section header's view:
This gives you the stickiness that you want because the section header will remain there even if you scroll past it and since the collection has only 2 sections the controls will always remain on top.
I think the collection/table paging part is the hardest part and I don't know clearly how it can be done. But I was thinking it could perhaps be a ContainerView. Each view of the container view would be either a tableview or a collectionview. You would have to add some code to handle the movement of the containerview relative to the second section header (possibly an autolayout constraint that attaches the containerview to the buttom of the first tableview that you implemented above).
I don't think having your tables/collections in a scrollview would be a good implementation. I think I have even read in documentation that developers should stay away from that (but I might be remembering it incorrectly).
I would have:
A "header view" with three subviews:
Fixed height top and bottom views (they stay visible at any size).
A middle view that appears/disappears as the superview grows/shrinks.
A scroll view (table or collection view are subclasses) on that partially covers the header view with a top inset set enough to reveal the underlying header view (the same way pull to refresh views are revealed).
The paging buttons could be set as table/collection view section header views.
Finally track the scroll view's scroll position to keep manually adjusting the header view height.
Another way to see this solution.
Two completely separated parts, a header view and a table view.
A simple header view (blue) that adjusts its subviews as its height changes. More precisely hides its middle subview (light blue) when it shrinks.
A table view that a) partially covers the header view in Interface builder but b) has a top inset as to avoid hiding the header view in the actual device (tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f);).
The two parts are only "connected" by resizing the header view height as the table view scrolls up/down.
I'm building a view which is a UITableView, however I want to anchor a "Write a comment" UITextField at the bottom of the screen. You can see an example of this on these screenshots from the "Secret" app - the "Write a comment (anonymously)" and "Post" button are anchored to the bottom of the screen regardless of whether you scroll the tableview items up or down.
What's the best way to achieve this?
Should I be embedding a UITableViewController into a UIViewController with the UIView anchored to the bottom of the screen and the tableview anchored to the top of this view?
Is this some kind of UITableView section footer?
Any advice greatly appreciated.
You could subclass UITableView and add a bottom view (not to confuse with a tableview's footerView). Since a UITableView is a subclass of UIScrollView, you can change its contentInsets so that the content of the tableview will still scroll above your bottom view.
tableView.contentInsets = UIEdgeInsetsMake(0, 0, 0, bottomViewHeight);
The next step would be to make the bottom view sticky, that is, floating with the bottom of the tableview. You can achieve this in multiple ways. Here are two suggestions:
1) Manipulating the frame directly
By conforming to UITableViewDelegate you automatically conform to UIScrollViewDelegate. You can see this by inspecting the protocol declaration in UITableView.h:
#protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>
Then implement scrollViewDidScroll:(UIScrollView *)scrollView and change the y-offset of the bottomview to always position it at the bottom of the view. UIScrollView's contentOffset property is used to determine how far down the scrollview has scrolled. This method will be called every single time the scrollview scrolls, hence it will appear that the bottom view sticks to the bottom of the tableview.
2) Use auto layout
While still changing the contentInsets as above, you can achieve the sticky effect by using auto layout constraints instead. By pinning the bottom view to the edge of the scrollview, it will automatically create the sticky effect for you. This is by far my recommended approach, since it saves lines of code, while it uses the highest possible level of abstraction.
I use this category by Florian Kugler when implementing auto layout in code.
This technical note, however not strictly related to the issue, describes how to use auto layout with scrollviews.
I have in-app chat (like whatsapp) and I have the following structure:
UIViewController
\
- View
\
- UITableView
- UIView (with textfied)
I thinks this is the best approach as you don't mix table data with anything else, and you don't have to juggle with sections in code
if you requirement is to show only one picture related information at once in screen means please follow the process it will help you.
first take a view controller then take an image view and on it the buttons you needed add them on image view only below image view take a tableview(if there are comments show tableview. if no comments available show a label as"be first to comment").
Hope this will help