I am having a (UIView and UICollectionView in a UIScrollView) as 1stVC. I have to scroll both at the same time for which I already unable the collection view scrolling. So first time When I launch that screen I am able to scroll the whole view, But when I push to (next ViewController) 2ndVC and then press Back Button to 1stVC my scroll view is not preforming it got Freeze.
Tried this Method:-
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^ {
CGRect contentRect = CGRectZero;
for(UIView *view in self.scrollView.subviews)
contentRect = CGRectUnion(contentRect,view.frame);
self.scrollView.contentSize = contentRect.size;
});
}
Tried this Method:-
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[_scrollView setContentSize:CGSizeMake(_scrollView.frame.size.width, _scrollView.frame.size.height)];
}
And For Getting Dynamic Height of the Collection view I have Done This
CGFloat height = _collectionCompass.contentSize.height;
Which I Have provided to ScollView ContentSize.
_scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width, height);
Please help me.
What I really suggest it's to remove scroll view and do all stuff in collection view, since with scroll view you're missing some of benefits (e.g. cells reusing). Also collection view in scroll view it's a bad practice.
From Apple style guide:
Don’t place a scroll view inside of another scroll view. Doing so creates an unpredictable interface that’s difficult to control.
If your UI as list, you can add view as header of collection view or as another cell. With this approach you can remove the code from viewDidLayoutSubviews
I have a UITextView being in a UIScrollView. I want to determine which one to scroll based on the scrolling speed. If the speed is low, the inner text view should scroll, and if the speed is high, the outer scroll view should scroll.
I have tried using
[scrollView.panGestureRecognizer scrollView]
to check speed in the scrollView:WillBeginDragging method, but can not make what I want.
Could anyone help?
are you using text view or scrollview OR textview with scrollView.
in Text View may be it helps.
notesTextView.decelerationRate = UIScrollViewDecelerationRateFast;
and ScrollView maybe it helps.
scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
and
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate: (BOOL)decelerate
{
if( !decelerate )
{
NSUInteger currentIndex = (NSUInteger)(scrollView.contentOffset.x / scrollView.bounds.size.width);
[scrollView setContentOffset:CGPointMake(scrollView.bounds.size.width * currentIndex, 0) animated:YES];
}
}
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.
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
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