【问题标题】:iPhone: Draw rotated text?iPhone:绘制旋转文本?
【发布时间】:2010-12-14 19:10:39
【问题描述】:

我想在视图中绘制一些文本,旋转 90°。我对 iPhone 开发还很陌生,在网上翻了一下发现了许多不同的解决方案。我已经尝试了一些,但通常最终我的文本被剪掉了。

这里发生了什么?我正在在一个相当小的空间(表格视图单元格)中绘图,但必须有一种“正确”的方式来做到这一点……对吧?


编辑:这里有几个例子。我正在尝试在左侧的黑条上显示文本“12345”。

  1. 第一次尝试,来自RJShearman on the Apple Discussions

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSelectFont (context, "Helvetica-Bold", 16.0, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode (context, kCGTextFill);
    CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
    CGContextSetTextMatrix (context, CGAffineTransformRotate(CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f ), M_PI/2));
    CGContextShowTextAtPoint (context, 21.0, 55.0, [_cell.number cStringUsingEncoding:NSUTF8StringEncoding], [_cell.number length]);
    CGContextRestoreGState(context);
    


    (来源:deeptechinc.com

  2. 第二次尝试,来自zgombosi on iPhone Dev SDK。相同的结果(这里的字体略小,因此剪辑较少)。

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGPoint point = CGPointMake(6.0, 50.0);
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, point.x, point.y);
    CGAffineTransform textTransform = CGAffineTransformMakeRotation(-1.57);
    CGContextConcatCTM(context, textTransform);
    CGContextTranslateCTM(context, -point.x, -point.y);
    [[UIColor redColor] set];
    [_cell.number drawAtPoint:point withFont:[UIFont fontWithName:@"Helvetica-Bold" size:14.0]];
    CGContextRestoreGState(context);
    

    Attempt two. There is almost identical clipping http://dev.deeptechinc.com/sidney/share/iphonerotation/attempt2.png

【问题讨论】:

  • 确实有几种方法可以解决这个问题。提供一些关于你到底尝试了什么以及它到底是如何失败的细节(它是如何/在哪里被剪掉的?)将使回答更容易有用。

标签: iphone text drawing rotation


【解决方案1】:

事实证明,无论行高如何,我的表格单元总是初始化为 44px 高,因此我的所有绘图都从单元格顶部被剪裁了 44px。

要绘制更大的单元格,需要将内容视图的autoresizingMask 设置为

cellContentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

cellContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

...drawRect 以正确的大小调用。在某种程度上,这是有道理的,因为UITableViewCellinitWithStyle:reuseIdentifier: 没有提及单元格的大小,并且只有表格视图实际上知道每行将有多大,基于它自己的大小和它的代表对tableView:heightForRowAtIndexPath:的回复。

我阅读了Quartz 2D Programming Guide,直到绘图模型和函数开始变得有意义,并且绘制我的旋转文本的代码变得简单明了:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextRotateCTM(context, -(M_PI/2));
[_cell.number drawAtPoint:CGPointMake(-57.0, 5.5) withFont:[UIFont fontWithName:@"Helvetica-Bold" size:16.0]];
CGContextRestoreGState(context);

感谢您的提示,看来我已经准备好了。

【讨论】:

    【解决方案2】:

    使用:-

    label.transform = CGAffineTransformMakeRotation(- 90.0f * M_PI / 180.0f);
    

    其中 label 是 UILabel 的对象。

    【讨论】:

    • 谢谢,@Sorted!实际上,我没有使用UILabel——我在自定义表格视图单元格中绘图。
    【解决方案3】:

    这里有一个提示。我想你是在 drawRect 中绘制的。你为什么不在 drawRect 周围画一个框架,看看矩形有多大,如果这就是你被剪裁的原因。

    另一种方法是将文本放在 UILabel 中,然后在 cellForRowAtIndexPath 中创建单元格时将其旋转 90 度。

    【讨论】:

    • mahboudz 的建议可能是您阻力最小的路径。您可以使用以下命令将 UILabel 旋转 90 度: [label setTransform:CGAffineTransformMakeRotation(DegreesToRadians(-90.0f))];您只需要根据标签宽度计算单元格高度。 -马特
    【解决方案4】:

    你知道 UITableViewDelegate 方法heightForRowAtIndexPath 对吗?

    这是simple tutorial on various graphics level methods. 假设您知道您的文本有多大,您应该能够适当地调整表格视图的行大小。

    另外,我会检查以确保任何转换后的边界确实符合您的期望。 (使用调试器或日志语句来验证这一点)。

    【讨论】:

    • 我知道tableView:heightForRowAtIndexPath:,行本身很好。文本在转换过程中被剪裁,最终在单元格中间被截断。
    • 你能告诉我们你用来做转换的具体代码吗?
    【解决方案5】:

    对于@Sidncious 所说的,以及我通过堆栈溢出收集的内容,我想给出一个用法示例 - 附加我的代码以将标尺完全绘制到屏幕左侧,并旋转数字:

    RulerView : UIView
    
    
      // simple testing for iPhones (check for device descriptions to get all iPhones + iPads)
      - (float)getPPI
      {
          switch ((int)[UIScreen mainScreen].bounds.size.height) {
              case 568: // iPhone 5*
              case 667: // iPhone 6
                  return 163.0;
                  break;
    
              case 736: // iPhone 6+
                  return 154.0;
                  break;
    
              default:
                  return -1.0;
                  break;
          }
      }
    
      - (void)drawRect:(CGRect)rect
      {
          [[UIColor blackColor] setFill];
    
    
          float ppi = [self getPPI];
    
          if (ppi == -1.0)  // unable to draw, maybe an ipad.
              return;
    
          float linesDist = ppi/25.4; // ppi/mm per inch (regular size iPad would be 132.0, iPhone6+ 154.0)
    
          float linesWidthShort = 15.0;
          float linesWidthMid = 20.0;
          float linesWidthLong = 25.0;
    
          for (float i = 0, c = 0; i <= self.bounds.size.height; i = i + linesDist, c = c +1.0)
          {
              bool isMid = (int)c % 5 == 0;
              bool isLong = (int)c % 10 == 0;
    
              float linesWidth = isLong ? linesWidthLong : isMid ? linesWidthMid : linesWidthShort;
              UIRectFillUsingBlendMode( (CGRect){0, i, linesWidth, .5} , kCGBlendModeNormal);
    
    
    
              /*  FONT: Numbers without rotation (yes, is short)
              if (isLong && i > 0 && (int)c % 10 == 0)
                  [[NSString stringWithFormat:@"%d", (int)(c/10)] drawAtPoint:(CGPoint){linesWidthLong +2, i -5} withAttributes:@{
                                                                                                                                  NSFontAttributeName: [UIFont systemFontOfSize:9],
                                                                                                                                  NSBaselineOffsetAttributeName: [NSNumber numberWithFloat:1.0]
                                                                                                                                  }];
              */
    
    
              // FONT: Numbers with rotation (yes, requires more effort)
              if (isLong && i > 0 && (int)c % 10 == 0)
              {
                  NSString *str = [NSString stringWithFormat:@"%d", (int)(c/10)];
                  NSDictionary *attrs = @{
                                          NSFontAttributeName: [UIFont systemFontOfSize:9],
                                          NSBaselineOffsetAttributeName: [NSNumber numberWithFloat:0.0]
                                          };
                  CGSize textSize = [str sizeWithAttributes:attrs];
    
    
                  CGContextRef context = UIGraphicsGetCurrentContext();
                  CGContextSaveGState(context);
    
                  CGContextRotateCTM(context, +(M_PI/2));
                  [str drawAtPoint:(CGPoint){i - (textSize.width/2), -(linesWidthLong + textSize.height +2)} withAttributes:attrs];
    
                  CGContextRestoreGState(context);
              }
    
          }
      }
    

    【讨论】:

      【解决方案6】:

      在我发现我需要将以下内容添加到我的文件顶部之后,我喜欢了 Matt 的方法。很简单。

      #define degreesToRadian(x) (M_PI * (x) / 180.0)
      

      mahboudz 的建议可能是您阻力最小的路径。您可以使用以下命令将 UILabel 旋转 90 度: [label setTransform:CGAffineTransformMakeRotation(DegreesToRadians(-90.0f))];您只需要根据标签宽度计算单元格高度。 -Matt – Matt Long 11 月 10 日 0:09

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-13
        • 1970-01-01
        • 2010-12-26
        • 1970-01-01
        • 1970-01-01
        • 2011-03-11
        • 1970-01-01
        • 2014-07-01
        相关资源
        最近更新 更多