UIViewController and Autolayout subviews - ios

I'm using Masonry to set the constraints of the subviews.
The view controller is simple.
in viewDidLoad
-(void)viewDidLoad
{
[self.view addSubview: self.tableView];
self.view.backgroundColor = [UIColor whiteColor];
[self.tableView addSubview: self.botBtn];
[self.botBtn makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.tableView.bottom).with.offset(-20);
make.centerX.equalTo(self.tableView);
}];
}
The frame for the table view is CGRectMake(0,0,screen_width,screen_height),
but the button is outside of the screen and just on the top of the tableview.
I set the tableview frame in it's init method.
The button stays in the mid of the view horizontally so the autolayout seems work, but why it is positioned on the top of the tableview instead of staying on the bottom.

Firstly well done for using Masonry :D.
To your question, I don't think you're adding the button in the right way, I'm guessing you want to add a button to bottom of the tableview, so when you scroll to the bottom of the tableview you will see your button? If so, just create a UIView with a button and set the tableview's footer view, i.e. [self.tableView setTableFooterView:newView]; as described in this question, Adding a button at the bottom of a table view
Let me know if this is not what you're actually looking for, good luck.

Related

How to stop a UIView from scrolling with tableview?

I have a UITableViewController and I put a UIView right under the navigation item and above the actual table. The problem that I have is that the view scrolls with the tableview.
How would I get it to behave exactly like the nav bar, and have the items in the tableview scroll behind it.
Rather than having the view scroll, it should remain in its position and have everything go behind it. Sorry for reiterating, but I've found thats necessary sometimes.
The view you're placing above the cell in the storyboard becomes the table view's tableHeaderView.
You can make the header view appear fixed by resetting its frame.origin to the table view's bounds.origin every time the table view lays out its subviews:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIView *header = self.tableView.tableHeaderView;
CGRect frame = header.frame;
frame.origin = self.tableView.bounds.origin;
header.frame = frame;
}
Result:
Assuming you don't want the map view to move then you could set its user interaction to false.
Alternatively you could set the header of your tableView (if you only have one section) to the map view.

UIView over UIScrollView prevent it from scrolling

I have a UITableView, Each cell has a view like below image, a UIScrollView in background and another view on the UIScrollView.
UIScrollView contains multiple images and user should be able to see them by swiping right or left on the table cell, But as second View (red area) covered UIScrollview, Scrolling not work when I swipe my finger in this area, But in the top of red area it's ok and works perfect.
I see in the other application that have this feature that scrolling is possible in all cell height even when they have other views that covered the background.
I should be grateful if you share your suggestions with me :)
try disable userInteraction on the view in the red area, this will allow touches to pass though it. this can be done through the storyboard, or just go view.userInteractionEnabled = false
Keep this line of code in ViewDidLoad method:
[self.view setExclusiveTouch:YES];
And if this doesn't work add it for your tableview
[tableView setExclusiveTouch:YES];
Or else at the end you can add the swipe gesture to the tableview cell and call the selector and do which intended to be done.
Add Second view as a subview of firstView or ScrollView.
[scrollView addSubview:firstView];
[firstView addSubview:secondView];
For me the issue was that the view was not a subview of the UIScrollView. You can check this by setting a breakpoint somewhere in your UIScrollView or the parent view controller class and entering the following in your debugger window:
po myScrollView.subviews
Then check the output to make sure that your element is within the subviews.
scrollView.isScrollEnabled = false
and handle the scrolling by code.
func scrollToPage(page: Int) {
var frame = scrollView.frame
frame.origin.x = frame.size.width * CGFloat(page)
scrollView.scrollRectToVisible(frame, animated: true)
}
view.userInteractionEnabled = NO

Remove view on top or bottom of Uitableview hosted on Uitableviewcontroller?

I am currently trying to remove the top or bottom view from my tableview but the size of the whole tableview isnt just right. Here is what i did so far.
Created a TableviewController inside the Storyboard
Created a Class derived from UITableViewController and set
everything up like delegate etc.
Dragged a view to the top of the tableview inside the Storyboard
Created and connected an outlet named topview for this
In Viewwillappear i will remove that topview dependent of some value so i tried some things
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(foo){
[self.topView setHidden:YES];
// or
[self.topView removeFromSuperview];
// or
[self.topView setFrame:CGRectMake(0, 0, 0, 0)];
}
}
For example if i remove the view from superview the topview isnt available anymore but there is a big gap on top .. how can i remove this top view from my tableview without having this gap ?
I put some Screenshots to describe my Problem:
If you put it inside the tableview it is probably the tableHeaderView. Try this:
self.tableView.tableHeaderView = nil;
Should remove the view and update the tableview accordingly.
[self.tableview reloadData]
after removing topview or if you're using autolayout then you can use [self.view updateConstraints];

Adjust a UIScrollView height based on a UITableView

I have a UIScrollView which contains a UIView and a UITableView. My goal is to adjust the height of the UIScrollView to allow me to scroll the contents of the UIScrollView to a specific point.
Here is my view: It has a UIView up top and a UITableView down below.
When I scroll, I want the UIView to stop at a specific point like so:
The tableView would be able to continue scrolling, but the UIView would be locked in place until the user scrolled up and brought the UIView back to its original state.
A prime example of what I am trying to do is the AppStore.app on iOS 6. When you view the details of the app, the filter bar for Details, Reviews and Related moves to the top of the screen and stops. I hope this all made sense.
Thanks
I ended up going with a simpler approach. can't believe I didn't see this before. I created two views, one for the UITableView's tableHeaderView and one for the viewForHeaderInSection. The view I wanted to remain visible at all times is placed in the viewForHeaderInSection method and the other view is placed in the tableHeaderView property. This is a much simpler approach, I think than using a scrollview. The only issue I have run into with this approach is all my UIView animations in these two views no longer animate.
Here is my code.
[self.tableView setTableHeaderView:self.headerView];
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return self.tableViewHeader;
}
add yourself as a UIScrollViewDelegate to the UITableView and implement the - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView so that if your views are in their starter positions they do this:
- your UITableView animates its size to the second state:
[UIView animateWithDuration:.1f animations:^{
CGRect theFrame = myView.frame;
theFrame.size.height += floatOfIncreasedHeight;
myView.frame = theFrame;
}];
- your UIView animates its vertical movement
[UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionCurveLinear animations:^(void){
view.center = CGPointMake(view.center.x , view.center.y + floatOfVerticalMovement);
}completion:^(BOOL Finished){
view.center = CGPointMake(view.center.x , view.center.y - floatOfVerticalMovement);]
Finally always in the delegate implement – scrollViewDidScrollToTop: so that you know can animate back to the initial state (using the same techniques reversed).
UPDATE:
since your views are inside a scroll view, there is a simpler way if you are ok with the table view being partly out of bounds in your starter position (i.e. instead of changing size it just scrolls into view):
make the scroll view frame size as big as your final tableview + your initial (entire) view and place it at 0,0 (so its final part will be hidden outside of the screen)
scrollview.frame = CGRectMake(0,0,tableview.frame.size.width,tableview.frame.size.height + view.frame.size.height);
you make the container scrollview contents as big as the entire table view + the entire view + the amount of the view that you want out of the way when scrolling the table view.
scrollview.contentSize = CGSizeMake(scrollview.frame.size.width, tableview.frame.size.height + view.frame.size.height + floatOfViewHeightIWantOutOfTheWay);
you place the view one after the other in the scrollview leaving all the additional empty space after the table view
view.frame = CGRectMake(0,0,view.frame.size.width, view.frame.size.height);
tableview.frame = CGRectMake(0,view.frame.size.height, tableview.frame.size.width, tableview.frame.size.height);
now it should just work because since iOS 3 nested scrolling is supported
You can easily achieve this by setting the content size of the scrollView correctly and keep the height of the UITableView smaller than your viewcontroller's height, so that it fits the bottom part of the top UIView and the UITableView...
Another scenario is to split the top View in 2 parts.
The part that will scroll away and the part that will be visible.
Then set the part that will scroll away as the entire UITableView header and the part that will remain visible as the header view for the first table section.
So then you can achieve this with a single UITableView, without having to use a UIScrollView
What you're looking for is something like what Game Center happens to do with it's header which can actually be modelled with a table header, a custom section header view, and some very clever calculations that never actually involve messing with the frame and bounds of the table.
First, the easy part: faking a sticky view. That "view that's always present when scrolling the table" implemented as a section header. By making the number of sections in the table 1, and implementing -headerViewForSection:, it's possible to seamlessly make the view scroll with the tableview all for free (API-wise that is):
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,50)];
label.text = #"Info that was always present when scrolling the UITableView";
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor colorWithRed:0.243 green:0.250 blue:0.253 alpha:1.000];
label.textColor = UIColor.whiteColor;
return label;
}
Finally, the hard part: KVO. When the table scrolls, we have to keep the header up there sticky with regards to the top of the view's frame, which means that you can KVO contentOffset, and use the resultant change in value to approximate the frame that the view should stick to with a little MIN() magic. Assuming your header is 44 pixels tall, the code below calculates the appropriate frame value:
CGPoint offset = [contentOffsetChange CGPointValue];
[self.tableView layoutSubviews];
self.tableView.tableHeaderView.frame = CGRectMake(0,MIN(0,offset.y),CGRectGetWidth(self.scrollView.frame),44);
If the above is infeasible, SMHeadedList actually has a fairly great, and little known, example of how complicated it can be to implement a "double tableview". That implementation has the added benefit of allowing the "header" tableview to scroll with the "main" tableview.
For future visitors, I've implemented a much simpler version, albeit one that accomplishes the goal with Reactive Cocoa, and a little bit of a different outcome. Even so, I believe it may be relevant.
What if you break the UIView into the top and bottom. The bottom will be the info.
Set UITableView.tableHeaderView = topView in viewDidLoad
and the return bottomView as Section Header in delegate method to make it float:
(UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section
{
return bottomView;
}
Just using the UITableView can solve with your problem. it is not need to use another scroll view.
set your view as the header view of UITableView. Then add your present view to the header view.
complete - (void)scrollViewDidScroll:(UIScrollView *)scrollView; . Tn the function to check the contentoffset of scroll view, and set the present view's frame.

Add a footer to UITableView at the bottom

I am doing a slide menu using a UITableView and I have 2 options on the menu and I want to put a button at the bottom like in this image:
I try to do that add a tableFooterView like that.
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 500, 320, 70)];
footerView.backgroundColor = [UIColor blackColor];
self.tableView.tableFooterView = footerView;
However, the view appears just after the second cell, but I want it at the bottom.
Thanks for help.
No you shouldn't add any empty cells, that's just hacky. If you really need the button to be at the bottom, you should use layoutSubviews to control the frame of the tableView and the footerView.
- (void)layoutSubviews
{
[super layoutSubviews];
self.tableView.frame = // top 80% of the screen
self.footerView.frame = // bottom 20% of the screen
}
You should know that every UITableViewCell has its height and footer is part of a UITableView and will appear at the bottom of a UITableView. If you want to make your UITableView look like what that image shows, you should make sure that your cells are high enough to make sure that your UITableView are high enough so that footer will appear at the bottom of UITableView
My suggestion is to add extra "empty" cell(I mean a cell with no content but has a height).
Add a Container View with View Controller from storyboard. You can use autoresizing to set the buttons on right place.

Resources