UIPageControl showing incorrect page - ios

I've got a UIScrollView containing several tables, and a UIPageControl keeping track of which page the user is currently viewing. It works fine UNTIL i start scrolling up on the tableview, at which point the UIPageControl adjusts and says (incorrectly) that we are on the first page.
Here is my code:
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView {
if (pageControlIsChangingPage) {
return;
}
/*
* We switch page at 50% across
*/
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
}
and then this as well:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)_scrollView {
pageControlIsChangingPage = NO;
}
Not sure what exactly is causing this to happen . . . any ideas? Im stumped :(

I believe the issue was that both the UITableView and the UIScrollView, since they both had the delegates set to self, were calling the same scrollview methods. I added a tag to the main scrollview, and then accounted for it by performing a check on the Tag when adjusting the page, like so
if (_scrollView.tag == 100) {
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
}
finally

When you scroll the page, does it scrolls correctly?
if (pageControlIsChangingPage)
return;
It seems when you do not change page (i.e. you scroll the tableview instead), return'll not be executed. And so
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
part will be executed, at this moment, _scrollView.contentOffset.x will less than pageWidth / 2 (even can be 0), as you just scroll up/down, and as a result, the page turn out to be 1.

Related

How to next or previous in UIScrollview with pagging in iOS

My problem is: The scrollview has 5 pages, when the global value of current page is 2, I swipe to left or right, it always return to first page. I cannot change next/previous page with the current page. This is my code:
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView
{
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl_Portrait.currentPage = page;
[self loadDataInChartView:page];
}
Please give me some advice. Thanks in advance.
You need to change the page control only after the UIScrollview has ended scrolling
Make sure paging is enabled for best results
use
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl_Portrait.currentPage = page;
}

Move pagecontrol dots to match current view location

I have 5 pages and I want to start on the 3rd page. I have added some code to skip to the 3rd page
CGRect frame = self.predictionsScroll.frame;
frame.origin.x = frame.size.width * (pagesBefore);
frame.origin.y = 0;
[self.predictionsScroll scrollRectToVisible:frame animated:YES];
This works perfectly except the pageControl still shows that it is on the first page. If I drag the view a tiny bit it updates to where it is, but this should start on the middle dot. Here is my method for updating the pageControl page.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if (scrollView == self.predictionsScroll) {
CGFloat pageWidth = self.predictionsScroll.frame.size.width;
float fractionalPage = self.predictionsScroll.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pagecontrol.currentPage=page;
}
}
I have tried adding a manuel pagecontrol.currentPage = pagesBefore; But this does not seem to work.

Backward Scroll

Hi I have 10 images in UIScrollview now i can scroll forward like from 1 to 2,3,4,etc but in my project i need to scroll images backward direction also like from 1 to 10 to left hand side
this is my code
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
CGFloat pageWidth = cardsScrollView.frame.size.width;
NSUInteger page = floor((self.cardsScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
if(page + 1 == [flashCardArry count]){
for (NSUInteger i = 0; i < [flashCardArry count]; ++i) {
int nElements = [flashCardArry count] - i;
int n = (arc4random() % nElements) + i;
[flashCardArry exchangeObjectAtIndex:i withObjectAtIndex:n];
}
[self.cardsScrollView scrollRectToVisible:CGRectMake(self.cardsScrollView.frame.size.width * 0 , 0, self.cardsScrollView.frame.size.width, self.cardsScrollView.frame.size.height) animated:NO];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
CGFloat pageWidth = cardsScrollView.frame.size.width;
NSUInteger page = floor((self.cardsScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
You can simply do that by adding the imageViews from 10 to 1 on your scrollView and then you have se the contentOffset of you scrollview to point to the last image which is image 1.
So user wont be able to scroll right at first, he can scroll to left for next images.
So. In case if you want cyclic scrollview you would need next things:
1) hide scrollView indicators
scrl.showsHorizontalScrollIndicator = NO;
scrl.showsVerticalScrollIndicator = NO;
2) Add one item to beginning of the scroll view, and one item at the end
[5'] | [0][1][2][3][4][5] | [0']
| --- full_size--- |
3) Once user scrolls to 5' item we updating content offset by adding full_size
4) Once user scrolls to 0' item we updating content offset by subtracting full_size
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint contentOffset = scrollView.contentOffset;
// First item
if (contentOffset.x < page_size) { // We are now faking last page
scrollView.contentOffset += full_size; // Jumping to actual last page
}
// Last item
if (contentOffset.x > full_size) { // We are now faking first page
scrollView.contentOffset -= full_size; // Jumping to actual first page
}
}
5) To decrease amount of jumps (especially on the borders), you can add more 2 or more fake items from both side

UIScrollView delegate method scrollViewWillEndDragging: not working?

I am trying to use the scrollViewWillEndDragging: method to to roll my own paged UICollectionView with previews on either side similar to the App Store app. However using the code below the scrollview will only scroll to the desired rect if i stop dragging with no inertia (ie. just lift up my finger). If I flick with any amount of inertia the method still gets called but the scrollview does not scroll the desired rect, it just keeps scrolling?
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
{
int itemWidth = 280;
MyCollectionView *collectionView = (MyIndexedCollectionView *) scrollView;
int totalPages = [self.colorArray[collectionView.index] count];
int currentPage;
int nextPage;
if (lastContentOffset < (int)scrollView.contentOffset.x)
{
// moved right
NSLog(#"scrolling right");
double currentPageOffset = ceil((scrollView.contentSize.width -
scrollView.contentOffset.x) / itemWidth);
currentPage = totalPages - currentPageOffset;
nextPage = currentPage >= totalPages ? totalPages : currentPage + 1;
}
else if (lastContentOffset > (int)scrollView.contentOffset.x)
{
// moved left
NSLog(#"scrolling left");
double currentPageOffset = floor((scrollView.contentSize.width -
scrollView.contentOffset.x) / itemWidth);
currentPage = totalPages - currentPageOffset;
nextPage = currentPage <= 0 ? 0 : currentPage - 1;
}
int xOffset = (nextPage * itemWidth);
int nextOffsetPage = (totalPages - ((scrollView.contentSize.width - xOffset) /
itemWidth)) + 1;
[scrollView scrollRectToVisible:CGRectMake(xOffset,
0,
collectionView.bounds.size.width,
collectionView.bounds.size.height)
animated:YES];
}
After giving up on this method I tried using the scrollViewWillBeginDecelerating: method instead and the exact same code works perfectly?? The reason why i am looking to use the scrollViewWillEndDragging: method instead is for two reasons:
I would like to tweak the item it jumps to based on the velocity of the scroll
the scrollViewWillBeginDecelerating: method does not get called if you stop dragging by lifting your finger without any inertia.
Any ideas, am I misunderstanding what this callback is doing?
DOH!! Turns out i should have been using the targetContentOffset to set the offset i wanted to scroll to instead of scrollToRectToVisible: ala:
*targetContentOffset = CGPointMake(myTargetOffset, targetContentOffset->y);
RTFM :)

How do you wrap multiple UIViews in a rounded rectangle for sorting (picture attached)?

In the following picture, how do you have Multi-option picker and the horizontal scroller in the same white rounded rectangle? It looks great for sorting, and I'd love to implement something like that.
You need to have a UITableView with two sections (one named "section 1" and one named "section 2").
Each section has a single row, and each row's "cell" contains an option picker inside it's "Accessory View".
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/tableview_iphone/TableViewCells/TableViewCells.html
That option picker is not part of the system's library of controls, I don't know where it came from.
You could do the option picker as a UIScrollView, attaching a UIPageControl to it, inside a UIView, with two UIViews (or UIImageViews) providing the transparent fading effect. You add n-views to the scrollview, each with the same height/width. If you want the snap, which I imagine you will, track the current page with the UIScrollViewDelegates like so:
-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float pageWidth = scrollview.frame.size.width;
int page = floor((scrollview.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
[self scrollview:scrollview scrollToPage: page];
}
-(void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if( decelerate == FALSE )
{
float pageWidth = scrollview.frame.size.width;
int page = floor((scrollview.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
[self scrollview:scrollview scrollToPage: page];
}
}
And the scrollview:scrollToPage: method will give you the snap like so:
-(void) scrollview:(UIScrollView*) scrollview scrollToPage:(NSInteger) page
{
[_myPageControl setCurrentPage:page];
CGRect frame = scrollview.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
[scrollview scrollRectToVisible:frame animated:YES];
}

Resources