UIView over UIScrollView prevent it from scrolling - ios

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

Related

UIViewController and Autolayout subviews

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.

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.

ScrollviewDidScroll not called at each point

There is a button at the bottom of my view controller. When the user scrolls down the button has to be attached to the scrollview at certain height.
I need to attach a button to the scrollview, immediately when the contentOffset.y reaches a particular value. -(void) scrollviewDidScroll doesn't help me as there might be a jump in contentOffset when the user is scrolling fast. Any leads on this are helpful.
Also, whenever I add a subview to the scrollview, -(void) viewDidLayoutSubviews is called. Which in turn sets the contentOffset to {0,0}. How can I achieve the functionality I need?
I needed to do the same thing with a UITableView and for me using scrollViewDidScroll worked.
I created a view called staticBar and added it as a subview of the tableView, but I had to rearrange the tableview subviews for it to appear in the right place. I don't have my code in front of me, but in -scrollViewDidScroll: it looked something like this:
- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
CGFloat staticBarAdjustedY = _staticBarY - scrollView.contentOffset.y;
CGFloat scrollViewYFloor = scrollView.frame.size.height - _staticBar.frame.size.height;
// This way maximum Y the view can have is at the base of the scrollView
CGFloat newY = MIN( staticBarAdjustedY, scrollViewYFloor);
_staticBar.frame = (CGRect){ { _staticBar.frame.origin.x, newY}, _staticBar.frame.size}
}
I will check my code later today and add more details here.
Also, you said the scrollviewDidScroll has jumps in contentOffset, but it's worth mentioning that these jumps are the same that the scrollView uses to scroll its own view. So it's not like you are "losing" frames on this delegate method.
Hope it helps.
PS: So, here is the rest of my code.
//I place my custom view as a subview of the tableView below it's last subview
//The last subview is for scroll indicators.
WTButtonsBar *buttonBar = [[WTButtonsBar alloc] init];
[self.tableView insertSubview:buttonBar belowSubview:self.tableView.subviews.lastObject];
In scrollViewDidScroll:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//In my app I needed my view to stick to the top of the screen
//thats why I use MAX here
//self.buttonsBarOriginalY is the view's position in the scrollView when it isn't attached to the top.
CGFloat newY = MAX(scrollView.contentOffset.y, self.buttonsBarOriginalY)
[_buttonsBar setFrame:(CGRect){{0, newY}, _buttonsBar.frame.size}];
}

how to keep uiview in view

i have a view that is required to be stayed on the view when the user scroll up or down in a scrollview.
i managed to let it stay on top of the view but how can i allow it to stay at the bottom of the view when i scroll down ? EDIT: attached picture to explain better.
the view will alway be visible on the view.
-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog (#"Content Offset: %f", self.playlistTableview.contentOffset.y);
if (self.playlistTableview.contentOffset.y > playerPosition) // will keep the view at the top
{
CGRect newFrame = self.playerView.frame;
newFrame.origin.x = 0;
newFrame.origin.y = +self.playlistTableview.contentOffset.y;
[self.playerView setFrame: newFrame];
}
}
you can see how the NZD have a top overlay that stops
Try to add your ScrollView and Always Stay view in a container view. So it will not scroll when you do scroll the scroll view. and anytime you can change your always stay view to different frame to top or bottom as u needed
UIView--->
1st subview--->UIScrollView
2nd subview--->Don't ScrollMeView/Always Stay view
I think you have added your view in contain of UIScrollView.
I mean, main container for your view is UIScrollview, so it'll work as subview of UIScrollview and will follow scrollview properties.
Can you please try to add your view on main view.
[self.view addSubView:yourViewObj];
If that comes behind the scrollView, then please try with
[self.view bringSubviewToFront:yourViewObj];

Make UIView scroll with UITableView but pin to top out of view

I currently have a view controller that is comprised of a Navigation bar, followed by a UIView that has two UIButtons added as subViews. There is then a UITableView underneath that begins at the bottom of the container UIView.
At the moment, when the user scrolls the UITableView it goes behind the UIView and UIButtons. What I actually want to happen is for the UIView and UIButtons to move up with the table view but only by the value of their height which in this case is 58 pixels. The flow would be like this...
1) Table scrolls and the UIView moves with it for the first 58 pixels.
2) The user continues to scroll the table but the UIView "pins" itself just out of view under the navigation bar.
3) When the user scrolls the table back down the UIView is then picked up and dragged back into view. I believe the new Facebook app does something similar in the timeline.
I don't want to set the UIView as the TableHeaderView of the table as I also have a pull-to-refresh which then sits above the buttons and looks terrible. I've tried playing around with the contentOffset properties of the underlying scrollview of the table but have hit a brick wall.
Any advice on where to start would be appreciated.
Thanks
EDIT: I am gotten a little further and using this code to move the frame of the UIView.
-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog (#"Content Offset: %f", self.tableView.contentOffset.y);
NSLog (#"Button Frame: %f", self.btnBackground.frame.origin.y);
if (self.tableView.contentOffset.y > 0)
{
CGRect newFrame = self.btnBackground.frame;
newFrame.origin.x = 0;
newFrame.origin.y = -self.tableView.contentOffset.y;
[self.btnBackground setFrame: newFrame];
}
}
The problem now is that the scrollViewDidScroll delegate method doesn't get fired quickly enough if the table view is scrolled fast. The result is that the UIView doesn't quite make all way back to its original position when scroll quickly.
The scroll content offset is a good idea. Also if you tableview has only one section one approach is to do a custom header view representing the top level widgets. If there is more than one sections create an additional empty section which would return your custom header.
You can refer to this stack overflow post.
Customize UITableview Header Section
Well Asked Question (y)
well , for me i would first : use a main UIScrollView that contains both your topView and the tableView under it and that has the same width as your top UIView and UITableView and set its height to be height(tableView) + height(topView).
Second : since UITableView is a subClass of UISCrollView you can use scrollViewDidScroll delegate to know if the tableview is scrolled up or down.
in this cas you will have Two cases :
1) tableview is scrolled up = > you set the content offset of the main scrollView to be
[scrollView setContentOffset:CGPointMake(0, 58) animated:YES];
2) when the table view is scrolled down you can reset the content offset again
[scrollView setContentOffset:CGPointMake(0, 0) animated:YES];

Resources