带有约束和RTL的UIScrollView的奇怪行为

时间:2014-03-10 07:39:10

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

我有一个水平滚动视图,我可以动态添加视图。 在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以及它如何实际工作的图像 enter image description here

4 个答案:

答案 0 :(得分:1)

试试这个

#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

希望这会对你有所帮助

答案 1 :(得分:1)

这是我的示例代码。

//
//  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

希望它可以帮到你。

答案 2 :(得分:1)

听起来更好的方法可能是使用UICollectionView。然后,如果你想从右侧开始,你可能会做这样的事情:

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

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

答案 3 :(得分:1)

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

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

enter image description here

所以低于[_scroller addConstraints:_constraint];添加类似(伪代码)的内容:

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