在子视图中像选框一样滚动 UILabel

Posted

技术标签:

【中文标题】在子视图中像选框一样滚动 UILabel【英文标题】:Scrolling UILabel like a marquee in a subview 【发布时间】:2013-06-25 12:05:03 【问题描述】:

我在主视图中有一个带有文本的 UILabel - “非常长的文本”。正确的宽度应该是 142,但我已将其缩短为 55。

基本上我想实现一个选框类型的滚动,所以我编写了代码将它添加到子视图中并在该视图的范围内对其进行动画处理。

代码 --

    CGRect tempLblFrame = _lblLongText.frame;
    UIView *lblView = [[UIView alloc] initWithFrame:tempLblFrame];

    //Add label to UIView at 0,0 wrt to new UIView
    tempLblFrame.origin.x = 0;
    tempLblFrame.origin.y = 0;

    [_lblLongText setFrame:tempLblFrame];
    [_lblLongText removeFromSuperview];
    [lblView addSubview:_lblLongText];

    //SetClipToBounds so that if label moves out of bounds of its superview, it wont be displayed
    [lblView setClipsToBounds:YES];
    [lblView setBackgroundColor:[UIColor cyanColor]];
    [self.view addSubview:lblView];

之后我在模拟器上得到了这个输出 -->

当我使用此代码尝试动画时出现问题 -

    tempLblFrame.origin.x = -_lblLongText.intrinsicContentSize.width;        
    [UIView animateWithDuration:2.0 delay:1.0 options:UIViewAnimationOptionCurveLinear
                     animations:^
                         [_lblLongText setFrame:tempLblFrame];
                     
                     completion:^(BOOL finished) 
                         NSLog(@"completed");
                     ];

我希望我能看到整个“非常非常长的文本”,而不是只有“非常...”从左到右滚动。

为了解决这个问题我添加了一行代码——

    //Add label to UIView at 0,0 wrt to new UIView
    tempLblFrame.origin.x = 0;
    tempLblFrame.origin.y = 0;

    tempLblFrame.size.width = _lblLongText.intrinsicContentSize.width; //THIS LINE WAS ADDED

    [_lblLongText setFrame:tempLblFrame];
    [_lblLongText removeFromSuperview];
    [lblView addSubview:_lblLongText];

我认为全文将设置在新添加的 UIView 中,它会正确滚动。但是在模拟器中运行给了我这个--

再一次,只有“非常...”从左到右滚动。

我做错了什么?请帮忙!!

编辑

显然罪魁祸首是 AutoLayout。

我不知道为什么,但是一旦我取消选中视图的“使用自动布局” 在 XIB 中,一切都开始按预期工作。环境 tempLblFrame.origin.x = -_lblLongText.intrinsicContentSize.width;曾是 工作正常,卷轴也正常工作。

对此有何解释!!?

【问题讨论】:

为什么你不使用已经修复的开源控制? github.com/cbpowell/MarqueeLabel 首先我想自己尝试一些东西。其次,我必须对有很多标签的现有项目进行更改。我不想从每个 xib(iPad、iPhone)中删除每个标签,而是想尝试一种更省力的替代方法 【参考方案1】:

这个问题可能是Duplicate of。

虽然 Charles Powell 为MarqueeLabel 编写了很好的代码 sn-p,

也可以看看This link。

我希望这会对您有所帮助,并通过提供所需的输出来节省您的时间。

【讨论】:

【参考方案2】:

UILabel 设为文本的宽度(或更长),将UIView 设为您想要查看的滚动区域。然后将UIViewclipToBounds 设置为YES(您正在这样做)。然后,当您从左到右制作动画时,您只会看到 UIView 宽度的文本,因为它会剪切任何额外的子视图。只需确保滚动UILabel 的整个长度即可。

现在您正在将视图和标签的高度和宽度设置为相同的值。这就是为什么你得到的是剪裁的文本,而不是剪裁的标签。

【讨论】:

我希望视图的宽度保持相同的长度。正如我在上面的评论中提到的,我必须在一个大项目中更改很多标签,我不想更改 UI 中的大小。如果文本长于指定大小,我希望它滚动。 您不想在 IB 中更改尺寸? UILabel 不能滚动,因此在您将文本放入其中的那一刻,它会缩小文本或剪辑它(添加 ...)。你最终需要改变一些东西,我会推荐标签的宽度,这可能是最简单的。 我试过不使用临时 UIView。我添加了一个带有长文本的小 UILabel。这按预期剪切了文本。后来我以编程方式增加了宽度,我可以看到整个文本。这里必须有一个修复。 为什么当我添加tempLblFrame.size.width = _lblLongText.intrinsicContentSize.width;而不更改原点或textAlignment时,文本会疯狂向右移动。 我真的看不出你在哪里设置 contentSize 但我猜这是因为 UILabel 默认将其文本居中。因此,如果 contentSize 设置得非常大,它会向右移动(使其居中)【参考方案3】:

您在视图滚动视图中添加并在滚动视图中添加此标签。使用此代码

 scroll.contentSize =CGSizeMake(100 *[clubArray count],20);
NSString  *bname;
bname=@"";
for(int i = 0; i < [clubArray count];  i++)

    bname = [NSString stringWithFormat:@"%@  %@ ,",bname,[[clubArray objectAtIndex:i] objectForKey:@"bottle_name"]];
    [bname retain];


UILabel *lbl1 = [[UILabel alloc] init];
[lbl1 setFrame:CGRectMake(0,5,[clubArray count]*100,20)];
lbl1.backgroundColor=[UIColor clearColor];
lbl1.textColor=[UIColor whiteColor];
lbl1.userInteractionEnabled=YES;    
[scroll addSubview:lbl1];
lbl1.text= bname;

这是实现的代码。谢谢

【讨论】:

对不起,Darshan,但我似乎看不懂代码。什么是变量——“scroll”、“clubArray”?还要记住,我的 XIB 中已经有 UILabel。所以我编写了代码从主视图中提取它们并将它们添加到一个临时子视图顶部以滚动。所以我想避免[[UILabel alloc] init] 此代码用于自定义生成标签,该标签添加到滚动视图中并使用我的 clubarray 自动生成。所以我建议你使用动态标签。谢谢【参考方案4】:

显然罪魁祸首是 AutoLayout。

我不知道为什么,但是一旦我取消选中 XIB 中视图的“使用自动布局”,一切都开始按预期工作。设置tempLblFrame.origin.x = -_lblLongText.intrinsicContentSize.width; 工作正常,滚动也是如此。

不过,对此进行更好的解释肯定会有所帮助!

编辑:使用自动布局的解决方案 -

    //Make UIView for Label to sit in
    CGRect tempLblFrame = _lblLongText.frame;
    UIView *lblView = [[UIView alloc] initWithFrame:tempLblFrame];

    //#CHANGE 1 Removing all constraints 
    [_lblLongText removeConstraints:_lblLongText.constraints]; 

    //Add label to UIView at 0,0 wrt to new UIView
    tempLblFrame.origin.x = 0;
    tempLblFrame.origin.y = 0;
    //Set Full length of Label so that complete text shows (else only truncated text will scroll)
    tempLblFrame.size.width = _lblLongText.intrinsicContentSize.width;

    //#CHANGE 2 setting fresh constraints using the frame which was manually set 
    [_lblLongText setTranslatesAutoresizingMaskIntoConstraints :YES];
    [_lblLongText setFrame:tempLblFrame];
    [_lblLongText removeFromSuperview];
    [lblView addSubview:_lblLongText];

【讨论】:

以上是关于在子视图中像选框一样滚动 UILabel的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 11 中像点击状态栏一样调用缓慢滚动到顶部的动画?

Android Widget:Textview 在主页滚动时停止选取框

如何在 UITextView 中像提词器一样快速滚动文本?

在 Swift 中像 Tab View Controller 一样滑动 uiView

任正非:录用员工搞得像选内衣模特一样;谷歌高管:安卓现在和 iOS 一样安全 甚至更好 | ITDaily

在子视图上具有最大 y 位置的垂直 UIScrollView