【问题标题】:Strange behavior of UIScrollView with Constraints and RTL带有约束和 RTL 的 UIScrollView 的奇怪行为
【发布时间】:2014-04-13 05:22:21
【问题描述】:

我有一个水平滚动视图,我在其上动态添加视图。 在 LTR 语言上一切正常,我从左到右一个接一个地添加视图。 在 RTL 上,问题是视图总是添加到滚动的左侧,而不是像其他控制器一样添加到右侧,真的奇怪的员工认为视图的顺序被正确添加到在第一个视图的左侧,因此它们从右到左排序,但在 -x 上的滚动视图之外。

这是我添加新视图时的代码:

Tag* tag = [self.storyboard instantiateViewControllerWithIdentifier:@"tag" ];
[_scroller addSubview:tag.view];
[tags addObject:tag];
Tag* prev = nil
for (Tag* tag in tags)
{
    if (prev == nil)
    {
        [_scroller addConstraint:[NSLayoutConstraint constraintWithItem:tag.view 
                                                       attribute:NSLayoutAttributeLeading                                                                                          
                                                       relatedBy:NSLayoutRelationEqual
                                                                     toItem:_scroller
                                                                  attribute:NSLayoutAttributeLeading
                                                                 multiplier:1.0f
                                                                   constant:0]];
    }
    else
    {
        [_scroller addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[prev]-10-[tag]"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:@{@"tag" : tag.view, @"prev" : prev.view}]];
    }

    [_scroller addConstraint:[NSLayoutConstraint constraintWithItem:tag.view
                                                          attribute:NSLayoutAttributeCenterY
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:_scroller
                                                          attribute:NSLayoutAttributeCenterY
                                                             multiplier:1.0f
                                                               constant:0]];
    prev = tag;

}

这是它假设如何在 LTR 和 RTL 上工作以及它实际上是如何工作的图片

【问题讨论】:

  • 你的问题是 LTR 视图应该是 LTR 而 RTL 视图应该是 RTL...但是对于 RTL 你得到 LTR 视图是这个问题吗?
  • 不,它是混合的,当我在 RTL 上时,添加的视图(标签)被镜像并且它们是 RTL。视图的顺序也是 RTL,第二个留给第一个,依此类推。但 contentView 是 LTR,它从滚动视图的左边缘开始,距离更远。 [[tag3][tag2][tag1](scrollview的左边缘)--------(scrollview的右边缘)]
  • 您是否尝试过在这种情况下反转数组(假设原始为 1 2 3 使其显示为 3 2 1 )
  • 是的,我做到了,它没有得到我想要的结果。它从滚动视图的左边缘开始向右,应该是第一个视图在滚动视图的中间,它应该在右边并从那里开始到左边。
  • 你能把粗略的屏幕显示成你想要的样子吗

标签: ios uiscrollview autolayout right-to-left nslayoutconstraint


【解决方案1】:

UIScrollView 出现这种行为的原因是您忘记将最后一个元素 (#4) 的 trailingAnchor 附加到滚动视图的 trailingAnchor

滚动视图和元素#1 的leadingAnchor 相互连接(见下文绿色部分)。然而,滚动视图的内容矩形自然地跨越到正坐标方向,从原点(0,0) 到右,向下(+x, +y)。在您的情况下,滚动视图的内容大小为宽度 0,因为滚动视图的 leadingAnchortrailingAnchor 之间没有任何内容。

所以在你的[_scroller addConstraints:_constraint];下面添加类似(伪代码):

if tag == lastTag {
  NSLAyoutconstraints.activate([
    tag.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor)
  ])
}

【讨论】:

    【解决方案2】:

    听起来更好的方法可能是使用UICollectionView。然后,如果您想从右侧启动它,您可以执行以下操作:

    NSIndexPath *lastIndex = [NSIndexPath indexPathForItem:data.count - 1 
                                                 inSection:0];
    [self.collectionView scrollToItemAtIndexPath:lastIndex 
                                atScrollPosition:UICollectionViewScrollPositionRight 
                                        animated:NO];
    

    这样UICollectionViewFlowLayout 可以为您处理展示位置。

    【讨论】:

    • 这不是必需的,请参阅下面我的帖子中的实际问题。
    【解决方案3】:

    这是我的示例代码。

    //
    //  ViewController.m
    //  testConstraint
    //
    //  Created by stevenj on 2014. 3. 24..
    //  Copyright (c) 2014년 Steven Jiang. All rights reserved.
    //
    
    #import "ViewController.h"
    
    
    @interface TagView : UILabel
    - (void)setNumber:(NSInteger)num;
    @end
    
    @implementation TagView
    
    - (void)setNumber:(NSInteger)num
    {
        [self setText:[NSString stringWithFormat:@"%d",num]];
    }
    
    @end
    
    @interface ViewController ()
    
    @property (nonatomic, strong) UIScrollView *scroller;
    @property (nonatomic, strong) NSMutableArray *tags;
    @property (nonatomic, strong) NSMutableArray *constraint;
    
    @end
    
    @implementation ViewController
    
    @synthesize scroller = _scroller;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        _tags = [NSMutableArray new];
        _constraint = [NSMutableArray new];
        // Do any additional setup after loading the view, typically from a nib.
    
        //step.1 create scroll view
        _scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 60)];
        [_scroller setBackgroundColor:[UIColor lightGrayColor]];
        [_scroller removeConstraints:[_scroller constraints]];
        [_scroller setTranslatesAutoresizingMaskIntoConstraints:YES];
    
        [self.view addSubview:_scroller];
    
    
        //step.2 add tag view
        for (int i=0; i<10; i++) {
            TagView *tag = [[TagView alloc] init];
    
            [tag setFrame:CGRectMake(100, 30, 50, 30)];
            [tag setNumber:i];
    
            [tag.layer setBorderWidth:1.0];
            [tag setTranslatesAutoresizingMaskIntoConstraints:NO];
    
            [_scroller addSubview:tag];
            [_tags addObject:tag];
        }
    
        //step.3 update contraints
        [self myUpdateConstraints];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void)myUpdateConstraints
    {
        [_constraint removeAllObjects];
    
        TagView* prev = nil;
        for (TagView* tag in _tags)
        {
            [tag setNumber:[_tags indexOfObject:tag]];
    
            if (prev == nil)
            {
    
                [_constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(<=300)-[tag]-20-|"
                                                                                         options:NSLayoutFormatDirectionLeadingToTrailing
                                                                                         metrics:nil
                                                                                           views:@{@"tag" : tag}]];
            }
            else
            {
                [_constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"[tag]-10-[prev]"
                                                                                  options:0
                                                                                  metrics:nil
                                                                                    views:@{@"tag" : tag, @"prev" : prev}]];
    
            }
    
            [_scroller addConstraint:[NSLayoutConstraint constraintWithItem:tag
                                                                  attribute:NSLayoutAttributeCenterY
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:_scroller
                                                                  attribute:NSLayoutAttributeCenterY
                                                                 multiplier:1.0f
                                                                   constant:0]];
    
            prev = tag;
    
        }
        [_scroller addConstraints:_constraint];
    }
    @end
    

    希望对你有帮助。

    【讨论】:

      【解决方案4】:

      试试这个

      #import "ViewController.h"
      
      @interface ViewController ()<UIScrollViewDelegate>
      {
      UIView *baseView;
      UILabel *titleLabel;
      NSMutableArray *infoArray ;
      UIScrollView *mainscrollview;
      }
      @end
      
      @implementation ViewController
      
      - (void)viewDidLoad
      {
      [super viewDidLoad];
      
      infoArray =[[NSMutableArray alloc]initWithObjects:@"1",@"2",@"3", nil];
         NSLog(@"%@",infoArray);
      mainscrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 380)];
      mainscrollview.delegate=self;
      mainscrollview.contentSize=CGSizeMake(320*infoArray.count, 0);
      [self.view addSubview:mainscrollview];
      [self sscrollcontent:@"LTR"];//LTR for Lefttoright other than LTR it will show RTL
      }
      -(void)sscrollcontent:(NSString *)flowtype
      {
      int xaxis=0;
      for (int i=0; i<infoArray.count; i++) {
          baseView=[[UIView alloc]initWithFrame:CGRectMake(xaxis, 0, 320, 380)];
          [mainscrollview addSubview:baseView];
          titleLabel =[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 60)];
          titleLabel.textAlignment=NSTextAlignmentCenter;
          if ([flowtype isEqualToString:@"LTR"]) {
              titleLabel.text=infoArray[i];
      
          }
          else
          {
              titleLabel.text=infoArray[infoArray.count-i-1];
      
          }
          [baseView addSubview:titleLabel];
          xaxis=xaxis+320;
      }
      }
      
      @end
      

      希望对你有帮助

      【讨论】:

      • 这个方法对我不起作用,因为我需要处理约束并在屏幕上同时拥有多个视图,而不是分页。
      猜你喜欢
      • 2013-03-16
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多