UITableView doesn't respond to scroll when parent frame is repositioned - ios

I'm building something similar to the Twitter composition panel in their mobile app. The top half of the view has a text area while the bottom half is a table view of images. You can scroll the table view up and it'll push the top view offscreen and only then you can scroll up and down the table view. What I have done is place my table view in a wrapper view and I change the frame of this to move both the tableview and the top view up and down (using a UIPanGestureRecognizer). The problem I have is once the wrapper view has moved up from its original position, only the section of the tableview which was originally visible can be scrolled. The previously offscreen part cannot scroll. Events are still bubbling up a couple view above.
Code below:
CGRect frame = self.tableView.frame;
frame.size.height = self.superview.frame.size.height;
[self.tableView setFrame:frame];
self.tableView.dataSource = dataSourceDelegate;
self.tableView.delegate = dataSourceDelegate;
self.tableView.index = index;
self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
self.panGesture.minimumNumberOfTouches = 1.0;
self.panGesture.delegate = self;
self.panGesture.maximumNumberOfTouches = 1;
self.panGesture.delaysTouchesBegan =YES;
self.panGesture.cancelsTouchesInView = YES;
[self.tableView reloadData];
[self.tableView addGestureRecognizer:self.panGesture];

It was a sizing issue for the table view. Although it appeared to be sized correctly, it was not which meant the content size was incorrect and therefore why the scroll didn't function as expected.

Related

How to implement both horizantal and vertical scroll in tableview in swift

I am new in swift and I am not able to scroll tableview horizontally for that I used Scrollview but it still not scrolling
But It is only showing
Not scrolling horizontally can somebody please help me. My structure is like this
Did somebody know how to convert this code to swift
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(x, x, x, x) style:...]
[scrollView addSubview:tableView];
// Set the size of your table to be the size of it's contents
// (since the outer scroll view will handle the scrolling).
CGRect tableFrame = tableView.frame;
tableFrame.size.height = tableView.contentSize.height;
tableFrame.size.width = tableView.contentSize.width; // if you would allow horiz scrolling
tableView.frame = tableFrame;
// Set the content size of your scroll view to be the content size of your
// table view + whatever else you have in the scroll view.
// For the purposes of this example, I'm assuming the table view is in there alone.
scrollView.contentSize = tableView.contentSize;
I have done the same as this.
Please find my screenshot

Un-scrollable table views inside scroll view

I have used a UIScroll View. It has a contentView (of type UIView) which again has a questionView (UIView) and 2 table views (UITableView). I want questionView and table views to scroll together so I disabled scrolling of table views hoping that scrollView will handle the scrolling. But its not happening. I suspect that the issue is with non-scrollable table views because of which Scroll view is not able to identify the right height of its contentView and hence, not scrolling. For enabling scroll, I added:
self.questionTableView.scrollEnabled = self.answerTableView.scrollEnabled = NO;
self.scrollView.delegate = self;
_scrollView.scrollEnabled = YES;
I read couple of questions on stack overflow but none of them fit my requirement.
set scroll view content size after table load
float sizeOfContent = 0;
NSInteger questionTblHight = self.questionTableView.contentSize.height;
NSInteger answerTbHight = self.answerTableView.contentSize.height;
sizeOfContent = questionTblHight+answerTbHight;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);

Several UICollectionViews Scroll Horizontally like iBooks

I am trying to do a view that contains several collectionViews. Swiping left or right would scroll to another collectionView.
I have added a scrollView as a first step with paging enabled. I also set the content size to the number of pages.
int nb_of_items = 10;
// Scroll view
for (int i=0; i< nb_of_items ; i++) {
CGRect frame = CGRectMake(_scrollView.frame.size.width * i,
0,
_scrollView.frame.size.width,
_scrollView.frame.size.height);
_collectionView.frame = frame;
[_scrollView addSubview:_collectionView];
}
_scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width * nb_of_items, _scrollView.frame.size.height);
_scrollView.delegate = self;
The collectionView is defined in my storyboard and has the datasource and delegate set to self. I am only getting the collection on the first page. On the other pages I get nothing.
I also tried to refresh the collection when the scrollView decelerates
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self updateCollection];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self updateCollection];
}
}
-(void)updateCollection{
NSLog(#"Updating Collection");
[_collectionView reloadData];
}
Any ideas how I could fix that ?
Remember that a collection view is a scroll view, so you already have the ability to scroll. You already know that scroll views can constrain the scrolling to full pages only. So, you can set the collection view to use pages and then the user can scroll between each part of your collection content.
All you need to do is to ensure that the layout scrolls in the correct direction (horizontal instead of vertical) and that each page has the appropriate contents. You probably want to create your own layout for that, though it could work with a flow layout so long as you set the item size appropriately.

Nested UIScrollViews and event routing

I have 2 scroll views, both of which are supposed to scroll vertically. The outer scroll view (red) contains a search bar and the inner scroll view (blue). The inner scroll view is supposed to scroll infinitely (it contains images/items and has an endless scrolling implementation).
The way I want this controller to work is as follows:
When I scroll down, the outer scroll view should scroll first and the search bar should disappear (scroll out of the content area). Only after that the inner scroll view should start scrolling.
When scrolling back up, the inner scroll view should scroll all the way to its top. Only then the outer scroll view should take the scroll events and finally scroll up to make the search bar visible again.
If I just nest them in IB without any modifications the inner scroll view catches all the scroll events and it works the other way around.
Please bear in mind that I'm using the inner scroll view as a simplifying metaphor here. In my app I actually have a control here, which has a scroll view with nested table views (scroll view lets me page horizontally, table views let me scroll vertically).
If you are able to, set a common UIScrollViewDelegate on the 2 scroll views, and implement the following:
- (void) scrollViewDidScroll: (UIScrollView*) scrollView
{
if (scrollView == self.mainScrollView)
{
/* Handle instances when the main scroll view is already at the bottom */
if ( scrollView.contentOffset.y
== scrollView.contentSize.height - scrollView.bounds.size.height)
{
/* Stop scrolling the main scroll view and start scrolling the
* inner scroll view
*/
self.innerScrollView.scrollEnabled = YES;
self.mainScrollView.scrollEnabled = NO;
}
else
{
/* Start scrolling the main scroll view and stop scrolling the
* inner scroll view
*/
self.innerScrollView.scrollEnabled = NO;
self.mainScrollView.scrollEnabled = YES;
}
}
else if (scrollView == self.innerScrollView)
{
/* Handle instances when the inner scroll view is already at the top */
if (self.innerScrollView.contentOffset.y == 0)
{
/* Stop scrolling the inner scroll view and start scrolling the
* main scroll view
*/
self.innerScrollView.scrollEnabled = NO;
self.mainScrollView.scrollEnabled = YES;
}
else
{
/* Start scrolling the inner scroll view and stop scrolling the
* main scroll view
*/
self.innerScrollView.scrollEnabled = YES;
self.mainScrollView.scrollEnabled = NO;
}
}
}
Please note that I haven't tested this, but the logic could be somewhat like this (either you set scrolling enabled or you disable user interaction, or something). Most probably this will not be enough of a solution as you would like, but I'm sure a common UIScrollViewDelegate is the solution to your problem.
I given the example for one scrollview, samething you have to create onemore scrollview and add based on dynamic height and content size it will work.
// .h file
#property (nonatomic, strong) UIScrollView *scrlSearch;
// .m File // ViewDidLoad
scrlSearch = [[UIScrollView alloc] init];
// For first scroll screen height was ((total screen height / 100 )* 10% )
// For Second scroll screen height was ((total screen height / 100 )* 90% )
scrlSearch.frame = CGRectMake(0, 0, (YourScreenWidth), (YourScreenHeight));
// YourVIEW = add any view to scrollbar
[scrlSearch addSubview:YourVIEW];
CGSize contentSize = scrlSearch.frame.size;
// YourContentHeight = dynamic content or static content height
contentSize.height = YourContentHeight;
// set the ContentHeight for scrolling
[scrlSearch setContentSize:contentSize];
// add the scrollview into delegate
[scrlSearch setDelegate:self];
Use just one scrollView and set the contentInset/contentOffset for the search bar. Something along this line:
UIEdgeInsets oldEdgeInset = [[self scrollView] contentInset];
CGRect f = [[self searchBar] frame];
UIEdgeInsets newEdgeInset = UIEdgeInsetsMake(CGRectGetMaxY(f), 0, 0, 0);
CGPoint offset = [[self scrollView] contentOffset];
offset.y += oldEdgeInset.top - newEdgeInset.top;
[[self scrollView] setContentOffset:offset];
[[self scrollView] setContentInset:newEdgeInset];
[[self searchBar] setFrame:f];
I am not sure about the structure you have and want to implement..
I have made a test project find here
But the project will definitely help you to manage different scrollviews all together..
The application might not be perfect though, but will give you some idea to achieve the solution.
Hope it helps..
Cheers
You should add inner scrollview on outer scrollview, but inner scrollview 'y' position should be content off set of outer scrollview like...
innerScrollView.frame = CGRectMake(10, outerScrollView.contentSize.height, 300, 440);
After this you can add any view on this innerScrollView, you can set contentOffset etc for innerScrollView.
Finally you should increase the contentSize for outer scrollview.
outerScrollView.contentSize = CGSizeMake(320, innerScrollView.frame.size.height+actualContentSizeOfOuterScroolView);
I think it helps for you!
Create a swipe gesture recognizer to your top-most view (above all the scroll views, on your view controller's view), and make it recognize UISwipeGestureRecognizerDirectionUp.
Then, you need to notify your controller whenever the outer scroll view scrolls.
Once it's scrolled down, add the gesture recognizer. When it hits the top again (outerScrollView.contentOffset == (0,0)), remove the gesture recognizer.
The gesture should 'eat' all the swiping events while it's present, making your inner scroll views to not receive the touch event and therefore will not scroll

ios:UITableView wont scroll to bottom

I have a scroll view with 3 UITableViews in it for paging. All of the UITableViews loads more cells of data. The first UITableView loads more cells than the other two. When viewing this first UITableView I am able to scroll to the bottom, but when I scroll to a second UITableView and back to the first UITableView I can no longer scroll all the way down. It seems as though I have to resize my scroll view. Why can't I scroll to the bottom after a view refresh? Any help would be great.
*The first UITableView has a search bar at the top. The other two do not. I tried removing the search bar, but the error still occurs.
//Create a frame for each page and add the page to the scroll view
- (void)frameToScrollView{
if (pages!=NULL) {
for (int i = 0; i < pages.count; i++) {
//Get the current view controller
UITableViewController *controller = [pages objectAtIndex:i];
//Create a frame for the current table view controller
CGRect frame = controller.view.frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
controller.view.frame = frame;
//Add the the current table view controller page to the scroll view
[self.scrollView addSubview:controller.view];
}
}
}
Set Other properties:
//Set the properties for the scroll view
- (void)setScrollViewProperties{
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * pages.count, self.scrollView.frame.size.height);
self.scrollView.contentOffset = CGPointMake(self.scrollView.frame.size.width, 0);
self.scrollView.scrollsToTop = NO;
}
UITableView is a subclass of UIScrollView. So you are basically adding 3 scrollviews to a scrollview. I dont think this is advisable.
I think the problem here is that the device is confused as to which scrollView will handle the touch/drag event.
If you really need the scrollView for paging, I suggest you create the scrollView, but disable touch event for this. You can add buttons to allow page navigation (instead of allowing user to do left/right swipe). This way, you can ensure that only the tableview that is visible is going to get the touch/drag event.
Found similar problem here: UITableView Won't Scroll In Certain Conditions.
My first UITableView has a search bar at top.
In the post above they recommend adding [self.tableView setAlwaysBounceVertical:YES];
I tested this and it does not work. I put it in my view did load for the UITableView.
Got it working:
(1) After "load more" cell is clicked and information is received I remove all subviews
(2) Then I create new frames and add them back to the subview
(3) Last I reload the table data

Resources