您的位置:首页 > 其它

iphone 上实现类似iphone自带股票软件下端的页面循环滚动

2010-03-09 19:35 465 查看
网上没有找到直接能用的详细方法。简单实现了一下。







在实现过程中发现 UIScrollView有以下部分特点:

1)没有动画结束通知。非常头疼,如果有提供代理接口就好了。

2)不会调用 touchBegin touchMove touchEnd 等 UIView的接口,在 sdk3.0以后,这几个接口在嵌套与其他 UIScrollView的UIScrollView里面不起作用。

3)在滚动的状态下,如果对视图进行了绘制操作或者 addSubview 的操作,则滚动的动画会卡。

4)在 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 代理接口里面,修改 contextOffset 之类的值不会起作用,这个接口最好就是记录一些状态,不要做 UIScrollview 相关的修改。







实现原理:将 UIScrollView 的 contextOffSet 的坐标,在滚动的边缘时进行改变,同时改变 UIScrollView 上 UIview
的center 属性,使 UIScrollView 上的元素能正确的改变。



实现过程:扩展 UIScrollView ,见附件的ExScrollView.h .m

设置自身为监听者,在具备一定的滚动状态判断条件下,调用 -
(void)setScrollPosition 实现设置。







设置 ExScrollView 的测试接口

-(void)setUpViews:(ExScrollView*)sview
{
    CGRect dddd = [sview frame];
    CGSize rcSize =    dddd.size;
    int nViewCount = 3;
    int perWidth = rcSize.width;
    CGRect rc = CGRectMake(0, 0, perWidth, rcSize.height);
    UIColor* color[6];
    color[0] = [UIColor brownColor];
    color[1] = [UIColor purpleColor];    
    color[2] = [UIColor orangeColor];    
    color[3] = [UIColor magentaColor];        
    color[4] = [UIColor yellowColor];    
    color[5] = [UIColor cyanColor];        
    int i=0;
    for(;i<nViewCount;i++)
    {
        UITextView* pView = [[UITextView alloc] initWithFrame:rc];
        UIColor* pColor = color[i%5];
        pView.backgroundColor = pColor;
        pView.text = [NSString stringWithFormat:@"%view:%d",i+1];
        pView.editable = NO;
        [sview addSubview:pView];
        [pView release];
        rc.origin.x += perWidth;
        pView.font = [UIFont systemFontOfSize:40];
        pView.tag = 0x12345691;
    }
    rcSize.width = nViewCount* rcSize.width;
    sview.contentSize = rcSize;
    sview.pagingEnabled = YES;
    sview.bounces = NO;
    CGPoint contextOff = {300,0};
    [sview setContentOffset:contextOff animated:NO];
}






UIScrollView的代理接口实现:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{//;      // called when scroll view grinds to a halt
	[self setScrollPosition];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{//; // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating
	[self setScrollPosition];
}






控制UIView偏移与 UIScrollView offset 位置的实现:

//调整位置
- (void)setScrollPosition
{
	if([self isPagingEnabled] == NO)
	{
		return;
	}
	
	if(self.dragging != NO && self.decelerating != NO)
	{
		return;
	}
	
	int x =	self.contentOffset.x;
	int totalWidth = self.contentSize.width;
	int perWidth = self.frame.size.width;
	
	int minStart = 4;
	int maxStart = totalWidth - perWidth - 4 ;
	if(!(x<minStart && x > minStart - perWidth) && !(x>maxStart && x < maxStart + perWidth))
	{
		return;
	}
	if(totalWidth <= perWidth*2)
	{
		return;//只有两个元素的情况
	}
	
	if(x < minStart || x >maxStart)
	{
		NSLog(@"self.contentOffset.x=%f",self.contentOffset.x);
		
		// 进入第一步,调整 contextOff 的位置
		int nx = 0;
		if(x < minStart)
		{
			nx = x + perWidth ;		
		}
		if(x >maxStart)
		{
			nx = x - perWidth;
		}
		CGRect rcVisable;
		rcVisable.origin.x = nx;
		rcVisable.origin.y = 0;
		rcVisable.size = self.frame.size;
		self.contentOffset = rcVisable.origin;
		
		//第二步 整理里面元素的位置 scrollView下面的视图偏移 (有两个 scrollView 自带的视图,排除 )
		//整理	
		NSArray* ary = 	[self subviews];
		int arySize = [ary count];
		NSMutableArray* aryOrderd = nil;//从 ary 里面的视图取出,按照当前 scrollview上从左到右再排序
		if(arySize > 0 )
		{
			aryOrderd = [[NSMutableArray alloc] initWithCapacity:0];
		}
		if(aryOrderd != nil)
		{
			int i = 0;
			//初开始化数组
			for(i=0;i<arySize;i++)
			{
				UIView* pView = [ary objectAtIndex:i];
				// 0x12345691 这个是我在增加 pView 到 scrollview 前给 pView 做的标记。用来区分 scrollview 内部的 view
				if(pView.hidden == NO && 0x12345691 == pView.tag)
				{
					[aryOrderd addObject:pView];
//					NSLog(@"初开始化数组 把pView=%d加入 %d ",pView, i);
//					NSLog(@"pView.center.x=%f ",pView.center.x);
				}
			}
			
			int aryOrdredSize = [aryOrderd count];
			NSArray* aryTemp = [[NSArray alloc] initWithArray:aryOrderd];
			//排序
			for(i=0;i<aryOrdredSize;i++)
			{
				UIView* pView = [aryTemp objectAtIndex:i];
				CGRect rccc = pView.frame;
				float centerX = CGRectGetMidX(rccc);
				int pageIndex = ceil(centerX/perWidth);	
				if(pView.hidden == NO && 0x12345691 == pView.tag)
				{
					if( pageIndex <= 0 || pageIndex > aryOrdredSize )
					{
//						NSLog(@"error calucate of page index");					
						int a=0;a=1/a;
					}
//					NSLog(@"排序中 把pView=%d插入 %d 位置",pView, pageIndex-1);
					[aryOrderd replaceObjectAtIndex:(pageIndex-1) withObject:pView];				
				}
			}
			[aryTemp release];
			
			//排完后开始整体挪动位置
			if(x < minStart)
			{
				NSLog(@"-----------------------need left round");
				//头位置放到最后,其他位置左移	
				
				for (i=0; i<aryOrdredSize; i++) 
				{
					UIView* pView = [aryOrderd objectAtIndex:i];
					if(i==(aryOrdredSize-1))
					{
						CGPoint centerPt = pView.center;
						centerPt.x = perWidth/2;
						pView.center = 	centerPt;					
					}				
					else
					{
						CGPoint centerPt = pView.center;
						centerPt.x += perWidth;
						pView.center = 	centerPt;	
					}					
					NSLog(@"================pView.center.x = %f",pView.center.x);
				}
				
			}
			if(x >maxStart)
			{
				//末尾位置放到前,其他位置右移				
				NSLog(@"-----------------------need right round");
				for (i=0; i<aryOrdredSize; i++) 
				{
					UIView* pView = [aryOrderd objectAtIndex:i];
					if(i==0)
					{
						CGPoint centerPt = pView.center;
						centerPt.x = totalWidth - perWidth/2;
						pView.center = 	centerPt;					
					}
					else
					{
						CGPoint centerPt = pView.center;
						centerPt.x -= perWidth;
						pView.center = 	centerPt;	
					}
					NSLog(@"================pView.center.x = %f",pView.center.x);
					if(pView.center.x > totalWidth )
					{
						int a=2;
						a++;
					}
				}
			}
		}
		[aryOrderd release];
	}
	
}




---------------------



最少支持3个循环滚动。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: