| 
[size=13px][size=12px]我有一个需求,做一个类似网易新闻客户端的标签 让标签rect滚动到可以显示的范围里则调用了 – (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated; 这个方法 但是没有作用代码如下
 – (void)viewDidLoad {[super viewDidLoad];
 // Do any additional setup after loading the view.
 
 self.view.backgroundColor = [UIColor yellowColor];
 self.automaticallyAdjustsScrollViewInsets = NO;
     scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 80, 320, 44)];scroll.contentSize = CGSizeMake(60*10, 0);
 for(int i=0; i<10; i++)
 {
 UIButton *bt = [[UIButton alloc]initWithFrame:CGRectMake(60*i, 0, 60, 44)];
 [bt setTitle:[NSString stringWithFormat:@”第%i块”,i] forState:UIControlStateNormal];
 bt.backgroundColor = [UIColor redColor];
 bt.tag = 1000+i;
 [scroll addSubview:bt];
 [bt addTarget:self action:@selector(pressBt:) forControlEvents:UIControlEventTouchUpInside];
 }
 scroll.delegate = self;
 scroll.backgroundColor = [UIColor clearColor];
 [self.view addSubview:scroll];
 }
 – (void)pressBt:(UIButton *)bt
 {
 [scroll scrollRectToVisible:bt.frame animated:YES];
 }[/size][/size]
 求大神赐教 | 
|  | 
button是作为scrollview 的子控件来添加的,所以button 的坐标系是相对于它的父视图scrollview来说的。但在uiscrollview 的 scrollRectToVisible :animated:要求的坐标系是相对于self.view来说的,所以你需要将button转换坐标系得到相对self.view的坐标位置,再使用scrollRectToVisible :animated: 来定位uiscrollview. 转换代码:
 CGRect  rect = [scroll  convertRect: btn.frame toView:self.view]; 完整代码如下: - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: btn.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
} | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行
 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
} | 
|  | 
应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) | 
|  | 

 | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
}
 应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) 
 这就是button当前相对于self.view的位置,它的位置就在这里,scrollRectToVisible 又定位在了这个位置,所以看不出变化。你是不是应该根据当前button 的位置做下判断,比如当button的x 坐标大于某个值时,让x的位置滚动到某个位置。如大于270时让它定位在200的位置,可以这样  - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    if (rect.origin.x > 270) {
             rect.origin.x -= 70;
             [scroll scrollRectToVisible:rect animated:YES];
   }
} | 
|  | 
- (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 | 
|  | 
- (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 你有没有实现 scrollView 的 Delegate 方法,比如 didScroll? | 
|  | 
有实现 我实现了一个 完成滚动时的代理
 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
}点击按钮时并不会调用他。滚动后调用这个代理, scrollRectToVisible方法似乎也没有起到作用 | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
}
 应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) 
 这就是button当前相对于self.view的位置,它的位置就在这里,scrollRectToVisible 又定位在了这个位置,所以看不出变化。你是不是应该根据当前button 的位置做下判断,比如当button的x 坐标大于某个值时,让x的位置滚动到某个位置。如大于270时让它定位在200的位置,可以这样  - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    if (rect.origin.x > 270) {
             rect.origin.x -= 70;
             [scroll scrollRectToVisible:rect animated:YES];
   }
} CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件"); 我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
}
 应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) 
 这就是button当前相对于self.view的位置,它的位置就在这里,scrollRectToVisible 又定位在了这个位置,所以看不出变化。你是不是应该根据当前button 的位置做下判断,比如当button的x 坐标大于某个值时,让x的位置滚动到某个位置。如大于270时让它定位在200的位置,可以这样  - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    if (rect.origin.x > 270) {
             rect.origin.x -= 70;
             [scroll scrollRectToVisible:rect animated:YES];
   }
} CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件"); 我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 这也真是太奇葩了。不行,你打包发上来,帮你看看。 | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
}
 应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) 
 这就是button当前相对于self.view的位置,它的位置就在这里,scrollRectToVisible 又定位在了这个位置,所以看不出变化。你是不是应该根据当前button 的位置做下判断,比如当button的x 坐标大于某个值时,让x的位置滚动到某个位置。如大于270时让它定位在200的位置,可以这样  - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    if (rect.origin.x > 270) {
             rect.origin.x -= 70;
             [scroll scrollRectToVisible:rect animated:YES];
   }
} CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件"); 我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 这也真是太奇葩了。不行,你打包发上来,帮你看看。 这不会传,我传百度网盘了 http://pan.baidu.com/s/1qWwo45e | 
|  | 
版主大人,好像不是这么回事 我又调整了代码 有用代理做了测试 也不行 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [scroll scrollRectToVisible:CGRectMake(0, 80, 60, 44) animated:YES];
    NSLog(@"代理");
}
 应该是没问题的。把convert出来后的rect 打印到控制台输出,看下是多少 NSLog(@"converted rect is :%@",NSStringFromCGRect(rect)) 
 这就是button当前相对于self.view的位置,它的位置就在这里,scrollRectToVisible 又定位在了这个位置,所以看不出变化。你是不是应该根据当前button 的位置做下判断,比如当button的x 坐标大于某个值时,让x的位置滚动到某个位置。如大于270时让它定位在200的位置,可以这样  - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    if (rect.origin.x > 270) {
             rect.origin.x -= 70;
             [scroll scrollRectToVisible:rect animated:YES];
   }
} CGRect  rect = [scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件"); 我把这个rect.origin.x 写死了0,如果scroll向右滚动过了,点击了bt就应该滚动到最左面但是确实没有这么显示 非常奇怪
 这也真是太奇葩了。不行,你打包发上来,帮你看看。 这不会传,我传百度网盘了 http://pan.baidu.com/s/1qWwo45e 看了你的代码,你这个 pressBt 实现不对,不应该用convertRect,直接用 button 的 frame 就行了。 
- (void)pressBt:(UIButton *)bt {
    CGRect  rect = bt.frame;//[scroll  convertRect: bt.frame toView:self.view];
    rect.origin.x = 0;
    [scroll scrollRectToVisible:rect animated:YES];
    NSLog(@"点击了事件");
}再来看convertRect方法,convertRect 是把 Rect 坐标映射到指定的 view 上的坐标,你的 button 又不是添加到 self.view 上的,映射成的坐标当然就不对了,比如你的 button 的 y 是0, 你映射成 self.view 的 y 就成了80(scroll 的 y),如果你一定要用convertRect方法的话有两种方案:1. 让 self.view 自身就是一个 scrollView,然后把 button 添加到 scrollView 上;
 2. 用这句CGRect rect = [scroll convertRect: bt.frame toView:scroll]代替。
 | 
|  20分
 | 
看了下,你是后来才改成用convertRect转换的,你是想点击5的时候让5全部显示吧:  
如果是那样的话,你的问题是出在 contentSize 上:
 
contentSize = CGSizeMake(60*10, 0); 你要让 scrollView 按 Rect 来滚动的前提是 contentSize 的 x、y 都不能为0,改在这样就ok 了: 
contentSize = CGSizeMake(60*10, 1); | 
|  20分
 | 
看你的代码了,可以用convert后的位置来判断是向左向右,再根据bt的frame来计算滚动的位置。我下面的代码是这样处理的,如果点击的位置超过了屏幕的一半,这样scroll就向左滑动,让被点击的按钮处在屏幕中间。如果计算得到的posX 小于 0 说明滚动到了头部。还是看代码吧:
 - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [self.scroll  convertRect: bt.frame toView:self.view];
    NSLog(@"rect is %@",NSStringFromCGRect(rect));
    CGFloat posX = 0;
    CGFloat halfWidth = 60/2;
    posX = bt.frame.origin.x-self.scroll.frame.size.width/2+halfWidth; /////让点击的按钮位置居中
    
    if (rect.origin.x >=self.scroll.frame.size.width/2 + halfWidth) {
        if(posX >= self.scroll.contentSize.width/2-halfWidth)
            posX = self.scroll.contentSize.width - self.scroll.frame.size.width; /////滚动到尾
    }else { //////向前滚动,判断是否到头了。
        if (posX <= 0)
            posX = 0;  /////滚动到头
    }
    
    [UIView animateWithDuration:0.3f animations:^{
        [self.scroll setContentOffset:CGPointMake(posX, 0)];
    }];
    
    NSLog(@"点击了事件");
} | 
|  | 
看了下,你是后来才改成用convertRect转换的,你是想点击5的时候让5全部显示吧:
  如果是那样的话,你的问题是出在 contentSize 上:
 
contentSize = CGSizeMake(60*10, 0); 你要让 scrollView 按 Rect 来滚动的前提是 contentSize 的 x、y 都不能为0,改在这样就ok 了: 
contentSize = CGSizeMake(60*10, 1);
 恩,改了 contentSize 确实好用了,谢谢版主了。问题解决。 | 
|  | 
看你的代码了,可以用convert后的位置来判断是向左向右,再根据bt的frame来计算滚动的位置。我下面的代码是这样处理的,如果点击的位置超过了屏幕的一半,这样scroll就向左滑动,让被点击的按钮处在屏幕中间。如果计算得到的posX 小于 0 说明滚动到了头部。还是看代码吧: - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [self.scroll  convertRect: bt.frame toView:self.view];
    NSLog(@"rect is %@",NSStringFromCGRect(rect));
    CGFloat posX = 0;
    CGFloat halfWidth = 60/2;
    posX = bt.frame.origin.x-self.scroll.frame.size.width/2+halfWidth; /////让点击的按钮位置居中
    
    if (rect.origin.x >=self.scroll.frame.size.width/2 + halfWidth) {
        if(posX >= self.scroll.contentSize.width/2-halfWidth)
            posX = self.scroll.contentSize.width - self.scroll.frame.size.width; /////滚动到尾
    }else { //////向前滚动,判断是否到头了。
        if (posX <= 0)
            posX = 0;  /////滚动到头
    }
    
    [UIView animateWithDuration:0.3f animations:^{
        [self.scroll setContentOffset:CGPointMake(posX, 0)];
    }];
    
    NSLog(@"点击了事件");
}
 问题解决了。 是由于 contentSize?=?CGSizeMake(60*10,?0); 的问题改为 contentSize?=?CGSizeMake(60*10,?1)变解决了 多谢版主耐心指导
 | 
|  | 
看你的代码了,可以用convert后的位置来判断是向左向右,再根据bt的frame来计算滚动的位置。我下面的代码是这样处理的,如果点击的位置超过了屏幕的一半,这样scroll就向左滑动,让被点击的按钮处在屏幕中间。如果计算得到的posX 小于 0 说明滚动到了头部。还是看代码吧: - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [self.scroll  convertRect: bt.frame toView:self.view];
    NSLog(@"rect is %@",NSStringFromCGRect(rect));
    CGFloat posX = 0;
    CGFloat halfWidth = 60/2;
    posX = bt.frame.origin.x-self.scroll.frame.size.width/2+halfWidth; /////让点击的按钮位置居中
    
    if (rect.origin.x >=self.scroll.frame.size.width/2 + halfWidth) {
        if(posX >= self.scroll.contentSize.width/2-halfWidth)
            posX = self.scroll.contentSize.width - self.scroll.frame.size.width; /////滚动到尾
    }else { //////向前滚动,判断是否到头了。
        if (posX <= 0)
            posX = 0;  /////滚动到头
    }
    
    [UIView animateWithDuration:0.3f animations:^{
        [self.scroll setContentOffset:CGPointMake(posX, 0)];
    }];
    
    NSLog(@"点击了事件");
}
 不需要这样,直接用scrollRectToVisible就行了 | 
|  | 
看你的代码了,可以用convert后的位置来判断是向左向右,再根据bt的frame来计算滚动的位置。我下面的代码是这样处理的,如果点击的位置超过了屏幕的一半,这样scroll就向左滑动,让被点击的按钮处在屏幕中间。如果计算得到的posX 小于 0 说明滚动到了头部。还是看代码吧: - (void)pressBt:(UIButton *)bt
{
    CGRect  rect = [self.scroll  convertRect: bt.frame toView:self.view];
    NSLog(@"rect is %@",NSStringFromCGRect(rect));
    CGFloat posX = 0;
    CGFloat halfWidth = 60/2;
    posX = bt.frame.origin.x-self.scroll.frame.size.width/2+halfWidth; /////让点击的按钮位置居中
    
    if (rect.origin.x >=self.scroll.frame.size.width/2 + halfWidth) {
        if(posX >= self.scroll.contentSize.width/2-halfWidth)
            posX = self.scroll.contentSize.width - self.scroll.frame.size.width; /////滚动到尾
    }else { //////向前滚动,判断是否到头了。
        if (posX <= 0)
            posX = 0;  /////滚动到头
    }
    
    [UIView animateWithDuration:0.3f animations:^{
        [self.scroll setContentOffset:CGPointMake(posX, 0)];
    }];
    
    NSLog(@"点击了事件");
}
 不需要这样,直接用scrollRectToVisible就行了 我的方式不可以?可能复杂了点,呵呵。 |