UISegmentedControl 中的两行文本

Posted

技术标签:

【中文标题】UISegmentedControl 中的两行文本【英文标题】:Two lines of text in a UISegmentedControl 【发布时间】:2013-11-08 20:52:17 【问题描述】:

尽我所能,我无法解决 ios7 iPhone 应用的 UISegmentedControl 错误。

创建分段控件时,我使用以下代码:

NSArray *segmentedControlItemArray = [NSArray arrayWithObjects: @"Nominal:\n27 inch", @"Actual:\n700c x 23mm", @"Actual:\n700c x 20mm", nil];
_wheelDiameterSegmentedControl = [[UISegmentedControl alloc] initWithItems:segmentedControlItemArray];
_wheelDiameterSegmentedControl.frame = CGRectMake(0, 102, 290, 50);
_wheelDiameterSegmentedControl.selectedSegmentIndex = 0;
_wheelDiameterSegmentedControl.tintColor = [UIColor colorWithRed:0.35 green:0.4 blue:0.9 alpha:1.0];

for (id segment in [_wheelDiameterSegmentedControl subviews]) 
    for (id label in [segment subviews]) 
        if ([label isKindOfClass:[UILabel class]]) 
            UILabel *titleLabel = (UILabel *) label;
            titleLabel.numberOfLines = 0;   
           
      


[_wheelDiameterSegmentedControl addTarget:self
                     action:@selector(pickOne:)
           forControlEvents:UIControlEventValueChanged];

[_wheelDiameterMenuContainer addSubview:_wheelDiameterSegmentedControl];

遗憾的是,我不能发布图片,或者我会向您展示我想要的控件的图片:UISegmented 控件中的每个段都有两行文本,在我要求的地方有一个换行符.

不过,在旋转时,我想保持分段控件全宽,而在这么宽的段中,换行符看起来很傻。因此,在 willAnimateRotationToInterfaceOrientation 中,我包含了以下代码,字符串中没有换行符:

    [_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 450, 50)];
    [_wheelDiameterSegmentedControl setTitle:@"Nominal: 27 inch" forSegmentAtIndex:0];
    [_wheelDiameterSegmentedControl setTitle:@"Actual: 700c x 23mm" forSegmentAtIndex:1];
    [_wheelDiameterSegmentedControl setTitle:@"Actual: 700c x 20mm" forSegmentAtIndex:2];

再一次,如果我可以插入图像,我会向您展示我想要的图像:一个宽 UISegmented 控件,标签中没有换行符(每个标签一行文本)。

这就是我遇到麻烦的地方。当我旋转回纵向时,我的选择似乎是:

1 行标签文本,被截断,格式为

“实际:7...”

当我刚刚重置 UISegmentedControl 的大小时使用

[_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 290, 50)];

2 行标签文本,被截断,格式为

“实际: 700c x ..."

当我重置大小并重置字符串值并重新运行将标签的 numberOfLines 设置为 2 的代码循环时,使用

    NSArray *segmentedControlItemArray = [NSArray arrayWithObjects: @"Nominal:\n27 inch", @"Actual:\n700c x 23mm", @"Actual:\n700c x 20mm", nil];

    [_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:0] forSegmentAtIndex:0];
    [_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:1] forSegmentAtIndex:1];
    [_wheelDiameterSegmentedControl setTitle:[segmentedControlItemArray objectAtIndex:2] forSegmentAtIndex:2];
    for (id segment in [_wheelDiameterSegmentedControl subviews]) 
        for (id label in [segment subviews]) 
            if ([label isKindOfClass:[UILabel class]]) 
                UILabel *titleLabel = (UILabel *) label;
                titleLabel.numberOfLines = 2;
            
        
    
    [_wheelDiameterSegmentedControl setFrame:CGRectMake(0, 102, 290, 50)];

3行标签文字,格式为

“实际: 700c x 20毫米"

当我将上面的强制 numberOfLines = 2 替换为我首先设置 UISegmentedControl 时起作用的 numberOfLines = 0 时,我得到了这个结果。

我想要的是我在创建控件时得到的,也就是

“实际: 700c x 20mm"

但无论我尝试了什么(将字符串和 numberOfLines 代码放入 willRotateToInterfaceOrientation 或 didRotateFromInterfaceOrientation;在更改文本之前重新设置 UISegmentedControl 的框架;在更改文本后重新设置框架......),我拿不回我漂亮、整洁的两行标签。我在这里想念什么?

【问题讨论】:

【参考方案1】:

啊哈!操作系统在旋转时处理标签大小的方式与在创建标签时处理标签的方式不同。所以我强制标签框架的大小,使用

for (id segment in [_wheelDiameterSegmentedControl subviews]) 

    for (id label in [segment subviews]) 

        if ([label isKindOfClass:[UILabel class]]) 

            UILabel *titleLabel = (UILabel *) label;

            //inserting line here, to make the frame behave nicely:
            //
            titleLabel.frame = CGRectMake(0, 0, 97, 50);
            //
            //continuing as before

            titleLabel.numberOfLines = 0;

        
    

现在它完全按照我想要/期望的方式显示。呵呵!


如果您只是想在 UISegmentedControl 中获取两行(或更多)文本。使用 Herzian 的惊人技术!这只是另一个代码示例,可能对人们有所帮助...

self.yourSlider .. set the height manually (can't easily do it in XIB)
// now use amazing Herzian technology...
for (id segment in [self.yourSlider subviews])
    for (id label in [segment subviews])
        
        if ([label isKindOfClass:[UILabel class]])
            
            UILabel *titleLabel = (UILabel *) label;
            titleLabel .. set the width to say 80, per your layout;
            (the width us typically too low)
            titleLabel.numberOfLines = 0;
            
        

再次感谢您。

【讨论】:

它在 iOS 7 中不起作用,因为在 iOS7 及更高版本中,它们使用 UISegmentLabel 而不是 UILabel,并且 UISegmentLabel 以某种方式受到保护/私有类。【参考方案2】:

ios 7 中的工作代码:

我有一个有四个段的段控制器,我需要它在 2 行中用于文本。所以我在UISegmentedControl 的片段中添加了UILabel 作为subview,它运行良好。我已经尝试了所有其他方法,但在 ios 7 和 ios 8 中它现在运行良好。

for(int k =0;k<4;k++)
    
        NSString *text = @"title name";
        UILabel *label = [[UILabel alloc] init];
        label.frame = CGRectMake(10,2, (self.segmentcontroll.frame.size.width/4), 34);
        label.font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
        label.textColor = [UIColor whiteColor];
        label.text = text;
        label.numberOfLines = 0;
        label.textAlignment = NSTextAlignmentCenter;
        [label sizeToFit];
        [[[self.segmentcontroll subviews] objectAtIndex:k] addSubview:label];

【讨论】:

好主意,但是 [[self.segmentcontroll subviews] objectAtIndex:k] 并不总是按从左到右的顺序返回 @david72 是的,你是对的。但我们可以通过任何一种方式来管理它。通过标签或文本或任何其他条件。【参考方案3】:

如果有人想要的话,还有 Herzian 的解决方案作为一个类别。请记住在 VWA 而不是 VDL 中调用它,以便在自动调整大小/旋转之后发生

#import "UISegmentedControl+MultiLine.h"

@implementation UISegmentedControl (MultiLine)

-(void)setupMultiLine

  self.frame = CGRectMake(self.frame.origin.x,
                          self.frame.origin.y,
                          self.frame.size.width,
                          self.frame.size.height*1.6);
  for (id segment in self.subviews)
  
    for (id label in [segment subviews])
    
      if ([label isKindOfClass:[UILabel class]])
      
        UILabel *titleLabel = (UILabel*) label;
        titleLabel.frame = CGRectMake(0,
                                      0,
                                      titleLabel.frame.size.width,
                                      titleLabel.frame.size.height*1.6);
        titleLabel.numberOfLines = 0;

      
    
  


@end

【讨论】:

以上是关于UISegmentedControl 中的两行文本的主要内容,如果未能解决你的问题,请参考以下文章

颤动中的行文本填充问题

为啥 macOS 中的 SwiftUI 多行换行文本在 Preview 中有效,但在实际应用中无效?

如何使 Toast 中的 2 行文本彼此居中?

alignItems: center 防止 React Native 中的 flex 行文本换行

setCellFactory覆盖updateItem和换行文本

AS3:如何将数据网格中的数据保存到逐行文本文件中?