App Store app view layout - ios

I would like to create a view similar to the App Store's app view on the iPhone :
http://cl.ly/image/0Q1h273v3C00
Basically when you scroll down, part of the header remains fixed at the top :
http://cl.ly/image/3m0I3Y0t1901
Here's the approach I tried, but it doesn't work as expected :
I use a tableView as the 'global view'
In this example, my tableView header would be the top part with the app icon, name ... and UISegmentedControl
Below the header is my regular tableView with cells...
Then, I simply implement the method below :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Keeping the menu always visible when user scrolls
// 155 is the original y position of the menu (UISegmentedControl here)
if (scrollView.contentOffset.y > 155) {
self.menuView.frame = CGRectMake(0,
scrollView.contentOffset.y,
self.menuView.frame.size.width,
self.menuView.frame.size.height);
}
else {
self.menuView.frame = CGRectMake(0,
155,
self.menuView.frame.size.width,
self.menuView.frame.size.height);
}
}
The menu remains at the top position just as I want, but still it's not working as expected :
My tableView section headers overlap the menu when I scroll. The only fix I found is to put the header layer at the top using this code :
self.tableView.tableHeaderView.layer.zPosition = MAXFLOAT;
But now the scrollbar is hidden behind the header, so I'm not satisfied with this either
I also tried to use this call in viewDidLoad and ...viewForHeaderInSection
[self.tableView bringSubviewToFront:self.tableView.tableHeaderView];
but it just doesn't work, since the section headers are always added after the tableView header and I haven't found a way to know when the section headers are added, so I can put them behind the tableView header.
When I scroll down more than the menu's initial position, even though the menu remains fixed at the top, I can't click on it, all the events are going to the tableviewcell behind it.
Finally, I want to be able to keep the same header when I click on the other buttons of the UISegmentedControl, just like in the App Store app view, and just change the content below, but I don't want to include the same header each time in each of my views, I would like to make the header generic.
Does anyone have any ideas on how to tackle the problems I'm facing, or a different approach to this ?
P.S : Youtube does kinda the same thing for the channel view, but their solution is not as good as Apple's, as you can't move the content if you start scrolling from the header.
Thanks for your help!

Related

iOS UISegmentedControll change selectedIndex smoothly

The UISegmentedControl is placed in the UINavigationBar and has two elements (e.g #"One" and #"Two").
The UIViewController contains a UIScrollView with two pages with horizontal scrolling. The segmented control indicates wich of the pages is currently displayed. I know how this works, but I want to implement it so while scrolling the selected tab changes smoothly.
Just like in the Apple Music app...
So it turns out that setting the selected index of a segmented control is now animatable:
UIView.animateWithDuration(4) {
self.seg.selectedSegmentIndex = 1
}
So they must be doing that, coordinating it with the interactive scrolling of the view by setting the layer speed to 0 and changing the timeOffset, as I explain here: https://stackoverflow.com/a/22677298/341994

UITableView scrolls down when contentInset is set and UITextField in tableViewHeader becomes active

Problem
I'm trying too make a custom search text field, added to a UITableViewController, always stick to the top of the page.
Like this:
Everything works fine, but when I tap the search text field to becomeFirstResponder the tableView strangely scrolls down.
I have discovered that this only happens when I manually setts the contentInset for the UITableView. (So that the tableview section headers don't hides behind the search view)
How I have built it
Layers:
TableView
UIView (as UITableView.tableViewHeaderView)
UIView (to update the frame when the user scrolling the tableView)
UITextField (for search input)
Code for fixing the search view frame when user scrolls:
var rect = frame
rect.origin.y = scrollView.contentOffset.y + 64
frame = rect
I may be doing everything stupid, but I would like to have the view stick to the top, because the user will use search more than other apps. Any ideas?
My app requires iOS 8 so I have not been available to test this on iOS 7. I can make a screen recording if that helps.
UPDATE
I've created an example project with the same objects I'm using in my main project.
https://www.dropbox.com/s/qdlx0milebbuf3p/Search%20bug%20Example.zip?dl=0
It's a UIKit bug. To fix this I've created a subclass for UITableView to NEVER change the content offset when isScrollEnabled is NO.
.h
#interface CUISearchTableView : UITableView
#end
.m
#import "CUISearchTableView.h"
#implementation CUISearchTableView
- (void)setContentOffset:(CGPoint)contentOffset {
if (self.isScrollEnabled) {
[super setContentOffset:contentOffset];
}
}
#end
I'm not sure you need to do all that. If you'd just use a UIViewController and add a UITableView to that, then you could place the UISearchView anywhere ( i.e., the top of the view ). You just need to make sure that the UISearchView is the top-most view ( bring subview to front ).
I get that you're using a UITableViewController, but if you want to use your own search view instead of the TableViewController+Search then this is your best bet. The only thing that would be necessary is adding the top content offset ( which you're already doing ). you could then just delete the CUISearchTableView.
Does this make sense or am I missing something?

Single Tapping not being detected on dynamically created uibuttons

It was necessary to create a subclass of UIButton, lets call it subButton. These subButtons are instantiated one by one and dynamically added to an UIScrollView object.
Unfortunately the subButtons aren't reacting as expected. After scrolling away from the first dynamic generated subButtons and then returning back to them. They loose their reactivity to single tapping. I can not explain this behaviour. Can somebody explain why its behaving this way?
Many thanks.
Source code
self.subButton = [[SubButton alloc]initWithFrame:CGRectMake(69.5, y, 201, 114)];
[self.subButton setBackgroundColor:[UIColor blueColor]];
self.subButton.imageData = imageData;
self.subButton.videoPath = videoPath;
self.subButton.vidIndex = _indexVideo +1;
[self.subButton drawVidPreview];
[self.subButton setTag:(_indexVideo +1)];
[self.subButton addTarget:self action:#selector(handleSingleTap:) forControlEvents:UIControlEventTouchUpInside];
[self.videoScroll addSubview:self.subButton];
[_videoPreviews addObject:self.subButton];
The subButton method drawVidPreview adds some subviews to itself.
Do the buttons not respond at all, or just not to single-tap? That might help us help you.
If they don't respond at all, I would check your view hierarchy to make sure no other view (perhaps invisible) are sitting above your buttons. Or, perhaps are the buttons not being added to the parent view you think?
Please make sure you are not adding the same UIGestureRecognizer instance to all of the UIButtons, instead for each UIButton you need to add a separate instance, however all gesture instance can point to the same target.
At last, i could solve the problem. The reason why the first subButtons did not respond to single tapping with UIControlEventTouchDown is because the uiScrollview content offset was set to a negative y value. This first of all was not necessary and was done out of pure laziness. I corrected it by giving it a positive value.
So my conclusion is, if you do not set the content offset or content size of the scrollView correctly, some dynamically added buttons to the scrollView might not respond to tapping appropriately. This is even the case if all Buttons are placed completely on a uiScrollview object.
This I could confirm by playing around with the content size of the uiScrollview instance too. I changed size of the y value of uiScrollviews instance just by few points and then some of the last buttons did not respond to tapping anymore.
Just by increasing the content size of the y value again, made the buttons responsive again.

UIRefreshControl for "Pull Up" to refresh?

How do I add UIRefreshControl to bottom of a UIColloectionView? That means how does it work when It comes to Scroll up (to see old data or something)?
You can't use UIRefreshControl to do that, but if you're ok with a simpler solution, you could just set up your collection view to automatically load more data when you scroll to the bottom. (Incidentally, this is a far more common user interface ... the pull up to refresh is not common, but automatically retrieving more data when you hit the bottom is.)
The most primitive rendition of that would be to respond to the UIScrollViewDelegate method and determine if you've scrolled to the bottom of the collection view (which is, itself, a subclass of the UIScrollView):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
{
if (!self.isLoadingMoreData)
{
self.loadingMoreData = YES;
// proceed with the loading of more data
}
}
}
Even better, if you have more data to load, show a cell at the bottom, that says "please wait, loading more data", perhaps with a UIActivityIndicatorView. For example, if you have more data to load, add a section to the end with this one cell. If you format this additional cell properly (e.g. a single cell that goes all the way across the collection view), it could definitely render the effect you're looking for.
Here is a CCBottomRefreshControl category for UIScrollView class (parent of UICollectionView class) that implements bottomRefreshControl property. It's compatible with both iOS 6 and 7 native refresh controls.
You can't. You can't really customise UIRefreshControl at all.

Add a bunch of controls dynamically to screen in iOS

I am working on a screen where user selects an option from drop-down. Based on this selection he adds a bunch of controls to screen. My drop-down is at the bottom-right corner of the screen. It takes up 20-25% of screen space at the bottom. In the remaining 75% screen at the bottom i need to add 9 labels,6 UItext fields ,2 drop-downs and 2 buttons. I am attaching a markup here.
My question is: in ASP.NET, I have a repeater which has all the above controls. In one of the buttons named "Add More". If I click that button, it adds the same repeater at the bottom of the current one. Do we have anything like that in iOS? Like a repeater which has a bunch of controls and click add and that exact repeater is added at the bottom and so-on and so forth. If any ideas/new ideas based on my explanation pop-up then please let me know. Thanks.
The link
http://dl.dropbox.com/u/40597849/mockup2.png
So, the big rectangle to the right containing 8 labels, textboxes, drop-downs and the 2 buttons below it(one is named as "Add More") should be added again when user clicks on Add More. Please ask me if you need more information.
ITMCustomView *cView = [[ITMCustomView alloc] initWithFrame:frame];
cView.delegate =self;
CGPoint scrollPoint = CGPointMake(0.0, (frame.origin.y/400)*400);
[self.scrollView setContentOffset:scrollPoint animated:YES];
[self.scrollView addSubview:cView];
Initially the very first custom view i add, i add it with this frame size (187, 585, 350, 21); . Next whenever i hit add more i call this delegate
[self.delegate addNewSize:CGRectMake(187,self.y+ 400 , 400, 400)];
This calls the above 5 lines of code and makes a new custom view and adds it to scroll view. I store the self.y as the y value of whatever frame currently being built. So how do i make my scroll view move up and down freely. The screen shows the custom view as they are added but doesnt allow me to go up anymore. I wanted to suppose add the custom view 5 times and i added 4 i just want to scroll up , see i added 4 scroll down and just add 1 more custom view and do other processing with it. But my scroll view is non-functional and its stuck at the just added custom view disabling me to scroll up. If you need more information, please ask me. Thanks.
Use a custom view that contains all your views.
1.) Make a custom class myView which subclasses UIView.
2.) Add all the controls you need in that view class.
3.) include myView in your main view.
4.) initiate as many myView as you like and add them to your main view.
I hope that is clear enough to get you going.
Update: As to elaborate more on the comment bgoers made.
When you create a new class myView sub-classing UIView you get an empty sheet. This sheet will have the frame that you specify either in the class or when you initiate (up to you). Within that frame (myView.h and myView.m in initWithFrame), you can add subViews like buttons or labels. Those subviews will placed relative to the sheet myView.
For example, your draw up is a custom view with all the controls. I can have another one looking exactly like it by simply initiating another custom view without adding more subviews. All I need to do is move the second custom view to where I would like, all the subviews will follow.
I encourage you to read up on how to subclass and how that works in iOS. It is very simple once you get the hang of it.

Resources