zoukankan      html  css  js  c++  java
  • 【IOS】将字体大小不同的文字底部对齐

    从WP转IOS了,还是放不下......

    在项目中,要实现如图多个不同大小的文字   底部对齐的效果   像下面这样:

    (想要的效果)

    以为用三个UIFont不同的UILabel  之后让他们底部对齐就可以了,但是效果是下面这样的:

     (不想要的效果)

    底部完全不对齐呀,为什么"1314"比两边高出了那么多呀!!!!强迫症不能忍呀!!!

    --------------------------------------------------------------------------------

    对比:

    1.在Windows Phone中 控件是相对布局

    Windows Phone里面TextBlock需要设置一个固定的 宽度  和 高度 (至少我是这样做的)

    TextBlock不但可以将文字设置为水平居中、偏左、偏右,还能通过属性 

    text.VerticalContentAlignment=Top/Center/Bottom将文字置于顶部/居中/底部。(WP中发现也只能水平方向的)

    2.在IOS中 控件是绝对布局: 对于一个控件  需要设置它的frame(包括起始位置、高和宽)

    可以通过以下方法直接获取一个字符串的自适应的高度和宽度:(这点觉得比WindowsPhone好)

    CGSize labelSize = [@"1314" sizeWithAttributes:@{NSFontAttributeName:kLabelFont}];

    而原生的UIlabel只能设置textAlignment文字的水平偏移属性,而无法直接更改竖直方向的偏移。

    WindowsPhone中要实现上面的效果,只需将三个TextBlock置底,TextBlock内容居下,即可对齐。

    (这一点我突然的不确定了,好像很多时候我都是直接设置margin来手动对齐的,有空回WindowsPhone看看再修改。)

    [2016.5.25修改] WP中TextBlock也没有VerticalContentAlignment属性...

    弯路:

    所以在IOS处理这个问题的时候,我想着既然三个控件的底部都是对齐了的,只是高度不一样,能否仿照着WindowsPhone那样,

    将较高UILabel的内容("1314")竖直偏移到最底下呢?

    经过查阅  UILabel找到了这些:  

    不能直接调用  只能通过继承来重写

    // override points. can adjust rect before calling super. (在调用父类前  可以调整文本内容的位置TextRect)

    // label has default content mode of UIViewContentModeRedraw

    - (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines;  //重写来重绘文字区域

    - (void)drawTextInRect:(CGRect)rect;  //重写来重绘文本  重写时调用super可以按默认图形属性绘制

    所以为了改变text的位置, 我们只需要改变textRectForBounds的返回值rect,并且根据这个rect重绘文本就可以了

    1、关于contentMode,该模式为视图提供了多种模式用以适用框架矩形。如果对除UIVewContentModeRedraw之外的模式(如UIViewContentModeScaleToFill)都不满足需求,或者说有特定需要自定义绘制视图,可以设置为此值。那么将在视图适应框架矩形变化时缺省自动调用setNeedsDispllay或setNeedsDisplayInRect:,从而重绘视图。
    2、而向视图发送setNeedsDisplay(或setNeedsDisplayInRect:)消息时,无论此时contentMode为何种模式,都将强制调用drawRect:  

    主要代码:(这个代码网上一大把,自己找去) 

    - (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
    {          //方法里的形参bounds指的是UILabel的bounds   
        CGRect rc = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];  //text的bounds
        switch (_verticalAlignment) {
            case VerticalAlignmentTop:
                rc.origin.y = bounds.origin.y;  
                break;
            case VerticalAlignmentBottom:
                rc.origin.y = bounds.origin.y + bounds.size.height - rc.size.height;
                break;
            case VerticalAlignmentMiddle:
            default:
                rc.origin.y = bounds.origin.y + (bounds.size.height - rc.size.height) / 2;
                break;
        } 
        return rc;
    }
    - (void)drawTextInRect:(CGRect)rect
    {
        CGRect rc = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
        [super drawTextInRect:rc];
    }

    然而发现:对于自适应宽高(CGSize)的Label, 设置了verticalAlignment属性基本上没多大区别

    origin.x  origin.y 均为零   并且SIZE区别几乎没有  所有也不会有多大区别。

    这里我进行了一个对比:对于字符串@"1314",设置不同的UIFont 观察UILabel和内部的textRect的大小差别

    UIFont                                 1                                         50                                          100

    rc(text)                1.000000,2.333333        105.666667,61.000000          208.666667,120.666667

    bounds(label)      1.000000,2.193359        105.541992,60.667969          208.349609,120.335938

    相差                                    0,0.139974             0.124675,0.332031                0.317058, 0.330729

    rc居然还要比bounds大那么一点点,我认为为了文字不被截取,文字大小还是比其文字边框还要小的,

    并且针对不同大小的UIFont或字体类型,这种小的程度还是不一样的。

    所以就算设置verticalAlignment属性也发现不了什么区别。

    如果只将文字大小设置更大,导致rc比bounds大,那么文字部分就可能会被截取;

    如果只增加UILabel的大小,导致rc比bounds小,那么就会看到除了文字外多余的空白区域;

    对于后两者,设置verticalAlignment属性,就能够明显的看到上下偏移了。

    所以这种方案对于实现所需效果无效。

    终点: 

    找呀找呀  又找到了另外一种方法,可以通过attributedText属性让UILabel显示富文本

    实现一个字符串中包含不同颜色、字号等。

    我封装了一个方法:

    // 获取带有不同样式的文字内容
    //stringArray 字符串数组
    //attributeAttay 样式数组
    - (NSAttributedString *)attributedText:(NSArray*)stringArray attributeAttay:(NSArray *)attributeAttay{
      // 定义要显示的文字内容
        NSString * string = [stringArray componentsJoinedByString:@""];  //拼接传入的字符串数组
      // 通过要显示的文字内容来创建一个带属性样式的字符串对象
        NSMutableAttributedString * result = [[NSMutableAttributedString alloc] initWithString:string];
            for(NSInteger i = 0; i < stringArray.count; i++){
         // 将某一范围内的字符串设置样式 [result setAttributes:attributeAttay[i] range:[
    string rangeOfString:stringArray[i]]]; } // 返回已经设置好了的带有样式的文字 return [[NSAttributedString alloc] initWithAttributedString:result]; }

     以及其使用

       NSDictionary *attributesExtra = @{NSFontAttributeName:kLabelFont,//字号12
                                                  NSForegroundColorAttributeName: [UIColor orangeColor]};
      NSDictionary *attributesPrice = @{NSFontAttributeName:kPriceFont,//字号18
                                                   NSForegroundColorAttributeName: [UIColor orangeColor]};
      NSAttributedString *attributedString = [self attributedText:@[@"", @"1314", @""]
                                                     attributeAttay:@[attributesExtra,attributesPrice,attributesExtra]];
       UILabel *price = [[UILabel alloc]init]; 
      price.attributedText
    = attributedString;    CGRect rect = [attributedString boundingRectWithSize:CGSizeMake(self.width / 2, 100) options:NSStringDrawingUsesLineFragme ntOrigin context:nil];  //此方法获取到的是自适应的Rect,而不是CGSize 最大Size值为CGSizeMake(self.width / 2, 100)
    price.frame = CGRectMake(0,0,rect.size.width, rect.size.height);
  • 相关阅读:
    MySQL Binlog解析(2)
    在线修改GTID模式
    官方online ddl
    pt-osc原理
    pt-osc使用方法
    python基本数据类型
    第一句python
    搭建私有云kodexplorer
    frp搭建
    Linux下快速分析DUMP文件
  • 原文地址:https://www.cnblogs.com/yffswyf/p/5473884.html
Copyright © 2011-2022 走看看