Hi,

This has been bugging me for a while and today, I've managed to grab some time 
in order to try and get it working.

I based my class on the "Street Scroller" Sample App from Apple. The main 
methods that are important in "Street Scroller" are:


- (void)recenterIfNecessary
{
    CGPoint currentOffset = [self contentOffset];
    CGFloat contentWidth = [self contentSize].width;
    CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
    CGFloat distanceFromCenter = fabs(currentOffset.x - centerOffsetX);
    
    if (distanceFromCenter > (contentWidth / 4.0))
    {
        self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y);
        
        // move content by the same amount so it appears to stay still
        for (UILabel *label in self.visibleLabels) {
            CGPoint center = [self.labelContainerView convertPoint:label.center 
toView:self];
            center.x += (centerOffsetX - currentOffset.x);
            label.center = [self convertPoint:center 
toView:self.labelContainerView];
        }
    }
}


- (void)tileLabelsFromMinX:(CGFloat)minimumVisibleX 
toMaxX:(CGFloat)maximumVisibleX
{
    // the upcoming tiling logic depends on there already being at least one 
label in the visibleLabels array, so
    // to kick off the tiling we need to make sure there's at least one label
    if ([self.visibleLabels count] == 0)
    {
        [self placeNewLabelOnRight:minimumVisibleX];
    }
    
    // add labels that are missing on right side
    UILabel *lastLabel = [self.visibleLabels lastObject];
    CGFloat rightEdge = CGRectGetMaxX([lastLabel frame]);
    while (rightEdge < maximumVisibleX)
    {
        rightEdge = [self placeNewLabelOnRight:rightEdge];
    }
    
    // add labels that are missing on left side
    UILabel *firstLabel = self.visibleLabels[0];
    CGFloat leftEdge = CGRectGetMinX([firstLabel frame]);
    while (leftEdge > minimumVisibleX)
    {
        leftEdge = [self placeNewLabelOnLeft:leftEdge];
    }
    
    // remove labels that have fallen off right edge
    lastLabel = [self.visibleLabels lastObject];
    while ([lastLabel frame].origin.x > maximumVisibleX)
    {
        [lastLabel removeFromSuperview];
        [self.visibleLabels removeLastObject];
        lastLabel = [self.visibleLabels lastObject];
    }
    
    // remove labels that have fallen off left edge
    firstLabel = self.visibleLabels[0];
    while (CGRectGetMaxX([firstLabel frame]) < minimumVisibleX)
    {
        [firstLabel removeFromSuperview];
        [self.visibleLabels removeObjectAtIndex:0];
        firstLabel = self.visibleLabels[0];
    }
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    [self recenterIfNecessary];
 
    // tile content in visible bounds
    CGRect visibleBounds = [self convertRect:[self bounds] 
toView:self.labelContainerView];
    CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
    CGFloat maximumVisibleX = CGRectGetMaxX(visibleBounds);
    
    [self tileLabelsFromMinX:minimumVisibleX toMaxX:maximumVisibleX];
}


I'm got to the stage where as far as I can see "recenterIfNecessary" just 
doesn't work correctly and I'm having difficulty trying to figure out what is 
actually supposed to do?

I am trying to scroll infinitely through the following images (these are Test 
Images so I can tell what is going on!), in the real app, these images will be 
downloaded. The height is fixed at 200 but the Width is Variable.

Index   File Name               ImageSize               XMin/XMax       

0       Image01.png             200,200                 0000,0199               
1       Image02.png             200,200                 0200,0399               
2       Image03.png             410,200                 0400,0809               
3       Image04.png             410,200                 0810,1219
4       Image05.png             200,200                 1220,1419
5       Image06.png             410,200                 1420,1829
6       Image07.png             200,200                 1830,2029
7       Image08.png             200,200                 2030,2229
8       Image09.png             200,200                 2230,2429

0/9     Image01.png             200,200                 2430,2629               
Wrap Around back to 0.


Total Width of all Images:      2430
 
In my Class, if I comment out the  "recenterIfNecessary" call, all my Views get 
added correctly and are shown in the correct order, and I can scroll them to 
the end and it stops as expected.

With "recenterIfNecessary" enabled,  as soon you begin the scroll and it runs 
Frame Recalculation Loop, the Views go all over the place. So, I'm pretty sure 
that this method is wrong (or at least my implementation of it is wrong, when 
you take the rest of the code with it).

This the a dump of the Frame Rect for each view before and after the center has 
been set.


Before myFramgeRect: {{0, 0}, {200, 200}}
After myFramgeRect: {{703, 0}, {200, 200}}
Before myFramgeRect: {{200, 0}, {200, 200}}
After myFramgeRect: {{903, 0}, {200, 200}}
Before myFramgeRect: {{400, 0}, {410, 200}}
After myFramgeRect: {{1103, 0}, {410, 200}}
Before myFramgeRect: {{810, 0}, {410, 200}}
After myFramgeRect: {{1513, 0}, {410, 200}}
Before myFramgeRect: {{1103, 0}, {410, 200}}
After myFramgeRect: {{492, 0}, {410, 200}}
Before myFramgeRect: {{1513, 0}, {410, 200}}
After myFramgeRect: {{902, 0}, {410, 200}}
Before myFramgeRect: {{1923, 0}, {200, 200}}
After myFramgeRect: {{1312, 0}, 

As you can see, the frame rect's are wildly off! 

I've attached my version of the methods from Street Scoller, if anyone can see 
where I am going wrong or how to correctly change the Frame Rectangles of the 
Scroll View subviews I'd be eternally grateful!

- (void) recenterContent
{
CGPoint                                 myCurrentOffset;
CGFloat                                 myContentWidth;
CGFloat                                 myCenterOffsetX;
CGFloat                                 myDistanceFromCenter;
CGPoint                                 myCenterPosition;
UIView*                                 myContentView;
CGPoint                                 myNewContentOffset;
CGRect                                  myFramgeRect;
CGRect                                  myBoundingRect;
        
myCurrentOffset = self.contentOffset;
myContentWidth = self.contentSize.width;

myBoundingRect = self.bounds;
myCenterOffsetX = (myContentWidth - myBoundingRect.size.width) / 2.0;

myDistanceFromCenter = fabs(myCurrentOffset.x - myCenterOffsetX);
if (myDistanceFromCenter > (myContentWidth / 4.0))
        {
        myNewContentOffset = CGPointMake(myCenterOffsetX,myCurrentOffset.y);
//      NSLog(@"myCurrentOffset   : %@",NSStringFromCGPoint(myCurrentOffset));
//      NSLog(@"myNewContentOffset: 
%@",NSStringFromCGPoint(myNewContentOffset));
        
        
        self.contentOffset = myNewContentOffset;

        for (myContentView in self.pContentVisiableArray)
                {
                myFramgeRect = myContentView.frame;
                NSLog(@"Before myFramgeRect: 
%@",NSStringFromCGRect(myFramgeRect));
                
                myCenterPosition = [self.pContentContainerView 
convertPoint:myContentView.center toView:self];
                myCenterPosition.x += (myCenterOffsetX - myCurrentOffset.x);
                myContentView.center = [self convertPoint:myCenterPosition 
toView:self.pContentContainerView];

                myFramgeRect = myContentView.frame;
                NSLog(@"After myFramgeRect: 
%@",NSStringFromCGRect(myFramgeRect));
        }
    }
}


- (CGFloat) addViewOnRight:(CGFloat) theRightEdge
{
NSInteger                                                       myContentIndex;
LTWScrollContentInfo*                           myContentInfo;
LTWInfinteScrollBaseView*                       myBaseView;
CGRect                                                          myFrameRect;
CGFloat                                                         myNewRightEdge;

myContentIndex = [self getContentIndexForXPosition:theRightEdge];
myContentInfo = [self getContentForIndex:myContentIndex];
myBaseView = [self newBaseViewWithContentInfo:myContentInfo];

//***** NSLog(@"theRightEdge: %f",theRightEdge);
[self dumpContentInfo:myContentInfo withIndex:myContentIndex 
andMessage:@"addViewOnRight"];

[self.pContentContainerView addSubview:myBaseView];
[self.pContentVisiableArray addObject:myBaseView];
        
myFrameRect = myBaseView.frame;
myFrameRect.origin.x = theRightEdge;
myFrameRect.origin.y = self.pContentContainerView.bounds.size.height - 
myFrameRect.size.height;
myBaseView.frame = myFrameRect;
myNewRightEdge = CGRectGetMaxX(myFrameRect);

#if 0
NSLog(@"addViewOnRight");
NSLog(@"theRightEdge:   %f",theRightEdge);
NSLog(@"myNewRightEdge: %f",myNewRightEdge);
NSLog(@"myContentIndex: %d",myContentIndex);
NSLog(@"myFrameRect:    %@",NSStringFromCGRect(myFrameRect));
NSLog(@"--------------------------------------");
NSLog(@"");
#endif

return myNewRightEdge;
}



- (CGFloat) addViewOnLeft:(CGFloat) theLeftEdge
{
NSInteger                                                       myContentIndex;
LTWScrollContentInfo*                           myContentInfo;
LTWInfinteScrollBaseView*                       myBaseView;
CGRect                                                          myFrameRect;
CGFloat                                                         myLeftEdge;

myContentIndex = [self getContentIndexForXPosition:theLeftEdge];
myContentInfo = [self getContentForIndex:myContentIndex];
myBaseView = [self newBaseViewWithContentInfo:myContentInfo];

//***** NSLog(@"theLeftEdge: %f",theLeftEdge);
[self dumpContentInfo:myContentInfo withIndex:myContentIndex 
andMessage:@"addViewOnLeft"];


[self.pContentContainerView addSubview:myBaseView];
//                      [self.pContentContainerView insertSubview:myBaseView 
atIndex:0];
[self.pContentVisiableArray insertObject:myBaseView atIndex:0];
        
myFrameRect = myBaseView.frame;
myFrameRect.origin.x = theLeftEdge - myFrameRect.size.width;
myFrameRect.origin.y = self.pContentContainerView.bounds.size.height - 
myFrameRect.size.height;
myBaseView.frame = myFrameRect;
myLeftEdge = CGRectGetMinX(myFrameRect);

return myLeftEdge;
}



- (void) adjustViewsFromMinX:(CGFloat) theMinimumVisibleX toMaxX:(CGFloat) 
theMaximumVisibleX
{
UIView*                                                         myFirstView;
UIView*                                                         myLastView;
CGFloat                                                         
myRightEdgePosition;
CGFloat                                                         
myLeftEdgePosition;

if ([self.pContentVisiableArray count] == 0)
    {
        [self addViewOnRight:theMinimumVisibleX];
    }

//**
//**    Add Views that are missing on Right side
//**
myLastView = [self.pContentVisiableArray lastObject];
myRightEdgePosition = CGRectGetMaxX(myLastView.frame);
while (myRightEdgePosition < theMaximumVisibleX)
    {
        myRightEdgePosition = [self addViewOnRight:myRightEdgePosition];
    }
        
//**
//**    Add Views that are missing on Left side
//**
myFirstView = [self.pContentVisiableArray objectAtIndex:0];
myLeftEdgePosition = CGRectGetMinX(myFirstView.frame);
while (myLeftEdgePosition > theMinimumVisibleX)
    {
        myLeftEdgePosition = [self addViewOnLeft:myLeftEdgePosition];
    }

//**
//**    Remove Views that have Fallen off the Right edge
//**
myLastView = [self.pContentVisiableArray lastObject];
while (myLastView.frame.origin.x > theMaximumVisibleX)
    {
        [myLastView removeFromSuperview];
        [self.pContentVisiableArray removeLastObject];
        myLastView = [self.pContentVisiableArray lastObject];
    }
    
//**
//**    Remove Views that have Fallen off the Left edge
//**
myFirstView = [self.pContentVisiableArray objectAtIndex:0];
while (CGRectGetMaxX(myFirstView.frame) < theMinimumVisibleX)
    {
        [myFirstView removeFromSuperview];
        [self.pContentVisiableArray removeObjectAtIndex:0];
        myFirstView = [self.pContentVisiableArray objectAtIndex:0];
    }
}




- (void) layoutSubviews
{
CGRect                                                          
myVisibleBoundingRect;
CGFloat                                                         
myMinimumVisibleX;
CGFloat                                                         
myMaximumVisibleX;

[super layoutSubviews];

self.showsHorizontalScrollIndicator = YES;

if (self.pScrollViewInfiniteScrollEnabled == NO)
        return;

if ([self.pContentArray count] == 0)
        return;


[self recenterContent];

myVisibleBoundingRect = [self convertRect:self.bounds 
toView:self.pContentContainerView];

myMinimumVisibleX = CGRectGetMinX(myVisibleBoundingRect);
myMaximumVisibleX = CGRectGetMaxX(myVisibleBoundingRect);
    
[self adjustViewsFromMinX:myMinimumVisibleX toMaxX:myMaximumVisibleX];
}

Thanks a lot
Dave






_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to