css style、css color 转 UIColor

你能看过来,就说明这个问题很好玩!IT开发是一个兴趣,更是一个挑战!兴趣使你工作有热情。挑战使让你工作充满刺激拉满的状态!我们日复一日年复一年的去撸代码,那些普普通通的功能代码,已经厌倦了!要的就是这种充满挑战最终攻克而带来快感!这种快感比那种快感让人感觉更得劲。。错了,可能是我老了吧~

因为业务开发需求,同样的功能三端(WEB、安卓 、iOS),而web端将数据封装成H5对应的标签方式,需要APP端来解析,将其文本提取出来倒没有什么技术难度,但核心问题是要取出相应的样式表渲染成正确的UI,这才是最困难的!

javascript 复制代码
 如<b><span style="color:orange,font-size:15px;">重要告警</span></b>

要把它显示成如下的原生页面,怎么办呢?来分析一下这些标签的作用:

javascript 复制代码
<b></b>意思是将里面的文本加粗显示

<span>标签普通的文本显示,但是文本的更多属性是在span的内联样式表中存放,我们要取出来颜色,字体大小来渲染为iOS的UILabel,通过setColor,setTextFont等API设置其显示样式! 

我得到的原始数据为:

javascript 复制代码
<b><a style="color:orange">【重要告警】</a></b>
<b>事件名称:</b>CCE-CPU监控;
<b>发生时间:</b>2023-11-08 09:48:00 GMT+08:00;
<b>事件源:</b>AOM;
<b>资源类型:</b>Application;
<b>指标名称:</b>aom_container_cpu_usage;
<b>最新指标值:  </b>45.95425;
<b>命名空间:</b>third-party;
<b>容器名称:</b>z-canal-test;
<b>告警信息:</b><br />阈值规则 CCE-CPU监控 状态从 "超限阈值" 变为 "正常" 。状态变化详细信息:指标名称为"aom_container_cpu_usage",最新指标数据取值"45.954",不满足阈值条件">90"。;
<b>修复建议:</b>建议进入容器  z-canal-test查看资源使用情况;

最终实现的显示效果为:

下面业结合开源的三方库来实现此功能的显示,第三方库:TFHpple

javascript 复制代码
#if __has_include("TFHpple.h")
#import "TFHpple.h"
#endif
 
@interface CSSStyleMap : NSObject
+ (NSDictionary *)cssColorMap;
 
#if __has_include("TFHpple.h")
+ (UIColor *)colorFromCssText:(NSString *)ctext;
+ (NSMutableArray <NSMutableDictionary *>*)stylesFromElement:(TFHppleElement *)e;
#endif
@end
javascript 复制代码
@implementation CSSStyleMap
//将CSS定义的颜色转为十六进制颜色
+ (NSDictionary *)cssColorMap
{
    NSString *k = @"{\
        \"CLEAR\": \"#00000000\",\
        \"TRANSPARENT\": \"#00000000\",\
        \"\": \"#00000000\",\
        \"ALICEBLUE\": \"#F0F8FF\",\
        \"ANTIQUEWHITE\": \"#FAEBD7\",\
        \"AQUA\": \"#00FFFF\",\
        \"AQUAMARINE\": \"#7FFFD4\",\
        \"AZURE\": \"#F0FFFF\",\
        \"BEIGE\": \"#F5F5DC\",\
        \"BISQUE\": \"#FFE4C4\",\
        \"BLACK\": \"#000000\",\
        \"BLANCHEDALMOND\": \"#FFEBCD\",\
        \"BLUE\": \"#0000FF\",\
        \"BLUEVIOLET\": \"#8A2BE2\",\
        \"BROWN\": \"#A52A2A\",\
        \"BURLYWOOD\": \"#DEB887\",\
        \"CADETBLUE\": \"#5F9EA0\",\
        \"CHARTREUSE\": \"#7FFF00\",\
        \"CHOCOLATE\": \"#D2691E\",\
        \"CORAL\": \"#FF7F50\",\
        \"CORNFLOWERBLUE\": \"#6495ED\",\
        \"CORNSILK\": \"#FFF8DC\",\
        \"CRIMSON\": \"#DC143C\",\
        \"CYAN\": \"#00FFFF\",\
        \"DARKBLUE\": \"#00008B\",\
        \"DARKCYAN\": \"#008B8B\",\
        \"DARKGOLDENROD\": \"#B8860B\",\
        \"DARKGRAY\": \"#A9A9A9\",\
        \"DARKGREY\": \"#A9A9A9\",\
        \"DARKGREEN\": \"#006400\",\
        \"DARKKHAKI\": \"#BDB76B\",\
        \"DARKMAGENTA\": \"#8B008B\",\
        \"DARKOLIVEGREEN\": \"#556B2F\",\
        \"DARKORANGE\": \"#FF8C00\",\
        \"DARKORCHID\": \"#9932CC\",\
        \"DARKRED\": \"#8B0000\",\
        \"DARKSALMON\": \"#E9967A\",\
        \"DARKSEAGREEN\": \"#8FBC8F\",\
        \"DARKSLATEBLUE\": \"#483D8B\",\
        \"DARKSLATEGRAY\": \"#2F4F4F\",\
        \"DARKSLATEGREY\": \"#2F4F4F\",\
        \"DARKTURQUOISE\": \"#00CED1\",\
        \"DARKVIOLET\": \"#9400D3\",\
        \"DEEPPINK\": \"#FF1493\",\
        \"DEEPSKYBLUE\": \"#00BFFF\",\
        \"DIMGRAY\": \"#696969\",\
        \"DIMGREY\": \"#696969\",\
        \"DODGERBLUE\": \"#1E90FF\",\
        \"FIREBRICK\": \"#B22222\",\
        \"FLORALWHITE\": \"#FFFAF0\",\
        \"FORESTGREEN\": \"#228B22\",\
        \"FUCHSIA\": \"#FF00FF\",\
        \"GAINSBORO\": \"#DCDCDC\",\
        \"GHOSTWHITE\": \"#F8F8FF\",\
        \"GOLD\": \"#FFD700\",\
        \"GOLDENROD\": \"#DAA520\",\
        \"GRAY\": \"#808080\",\
        \"GREY\": \"#808080\",\
        \"GREEN\": \"#008000\",\
        \"GREENYELLOW\": \"#ADFF2F\",\
        \"HONEYDEW\": \"#F0FFF0\",\
        \"HOTPINK\": \"#FF69B4\",\
        \"INDIANRED\": \"#CD5C5C\",\
        \"INDIGO\": \"#4B0082\",\
        \"IVORY\": \"#FFFFF0\",\
        \"KHAKI\": \"#F0E68C\",\
        \"LAVENDER\": \"#E6E6FA\",\
        \"LAVENDERBLUSH\": \"#FFF0F5\",\
        \"LAWNGREEN\": \"#7CFC00\",\
        \"LEMONCHIFFON\": \"#FFFACD\",\
        \"LIGHTBLUE\": \"#ADD8E6\",\
        \"LIGHTCORAL\": \"#F08080\",\
        \"LIGHTCYAN\": \"#E0FFFF\",\
        \"LIGHTGOLDENRODYELLOW\": \"#FAFAD2\",\
        \"LIGHTGRAY\": \"#D3D3D3\",\
        \"LIGHTGREY\": \"#D3D3D3\",\
        \"LIGHTGREEN\": \"#90EE90\",\
        \"LIGHTPINK\": \"#FFB6C1\",\
        \"LIGHTSALMON\": \"#FFA07A\",\
        \"LIGHTSEAGREEN\": \"#20B2AA\",\
        \"LIGHTSKYBLUE\": \"#87CEFA\",\
        \"LIGHTSLATEGRAY\": \"#778899\",\
        \"LIGHTSLATEGREY\": \"#778899\",\
        \"LIGHTSTEELBLUE\": \"#B0C4DE\",\
        \"LIGHTYELLOW\": \"#FFFFE0\",\
        \"LIME\": \"#00FF00\",\
        \"LIMEGREEN\": \"#32CD32\",\
        \"LINEN\": \"#FAF0E6\",\
        \"MAGENTA\": \"#FF00FF\",\
        \"MAROON\": \"#800000\",\
        \"MEDIUMAQUAMARINE\": \"#66CDAA\",\
        \"MEDIUMBLUE\": \"#0000CD\",\
        \"MEDIUMORCHID\": \"#BA55D3\",\
        \"MEDIUMPURPLE\": \"#9370DB\",\
        \"MEDIUMSEAGREEN\": \"#3CB371\",\
        \"MEDIUMSLATEBLUE\": \"#7B68EE\",\
        \"MEDIUMSPRINGGREEN\": \"#00FA9A\",\
        \"MEDIUMTURQUOISE\": \"#48D1CC\",\
        \"MEDIUMVIOLETRED\": \"#C71585\",\
        \"MIDNIGHTBLUE\": \"#191970\",\
        \"MINTCREAM\": \"#F5FFFA\",\
        \"MISTYROSE\": \"#FFE4E1\",\
        \"MOCCASIN\": \"#FFE4B5\",\
        \"NAVAJOWHITE\": \"#FFDEAD\",\
        \"NAVY\": \"#000080\",\
        \"OLDLACE\": \"#FDF5E6\",\
        \"OLIVE\": \"#808000\",\
        \"OLIVEDRAB\": \"#6B8E23\",\
        \"ORANGE\": \"#FFA500\",\
        \"ORANGERED\": \"#FF4500\",\
        \"ORCHID\": \"#DA70D6\",\
        \"PALEGOLDENROD\": \"#EEE8AA\",\
        \"PALEGREEN\": \"#98FB98\",\
        \"PALETURQUOISE\": \"#AFEEEE\",\
        \"PALEVIOLETRED\": \"#DB7093\",\
        \"PAPAYAWHIP\": \"#FFEFD5\",\
        \"PEACHPUFF\": \"#FFDAB9\",\
        \"PERU\": \"#CD853F\",\
        \"PINK\": \"#FFC0CB\",\
        \"PLUM\": \"#DDA0DD\",\
        \"POWDERBLUE\": \"#B0E0E6\",\
        \"PURPLE\": \"#800080\",\
        \"RED\": \"#FF0000\",\
        \"ROSYBROWN\": \"#BC8F8F\",\
        \"ROYALBLUE\": \"#4169E1\",\
        \"SADDLEBROWN\": \"#8B4513\",\
        \"SALMON\": \"#FA8072\",\
        \"SANDYBROWN\": \"#F4A460\",\
        \"SEAGREEN\": \"#2E8B57\",\
        \"SEASHELL\": \"#FFF5EE\",\
        \"SIENNA\": \"#A0522D\",\
        \"SILVER\": \"#C0C0C0\",\
        \"SKYBLUE\": \"#87CEEB\",\
        \"SLATEBLUE\": \"#6A5ACD\",\
        \"SLATEGRAY\": \"#708090\",\
        \"SLATEGREY\": \"#708090\",\
        \"SNOW\": \"#FFFAFA\",\
        \"SPRINGGREEN\": \"#00FF7F\",\
        \"STEELBLUE\": \"#4682B4\",\
        \"TAN\": \"#D2B48C\",\
        \"TEAL\": \"#008080\",\
        \"THISTLE\": \"#D8BFD8\",\
        \"TOMATO\": \"#FF6347\",\
        \"TURQUOISE\": \"#40E0D0\",\
        \"VIOLET\": \"#EE82EE\",\
        \"WHEAT\": \"#F5DEB3\",\
        \"WHITE\": \"#FFFFFF\",\
        \"WHITESMOKE\": \"#F5F5F5\",\
        \"YELLOW\": \"#FFFF00\",\
        \"YELLOWGREEN\": \"#9ACD32\"\
    }";
    
    NSDictionary *map = [JsonKit jsonObject:k];
    return map;
}
 
#if __has_include("TFHpple.h")
+ (UIColor *)colorFromCssText:(NSString *)val
{
    NSString *cl = [[CSSStyleMap cssColorMap] stringForKey:val];
    UIColor *color = nil;
    if (cl.length > 0)
    {
        color = [UIColor colorFromHex:cl];
    }
    else
    {
        val = [val stringByReplacingOccurrencesOfString:@"rgba(" withString:@""];
        val = [val stringByReplacingOccurrencesOfString:@"rgb(" withString:@""];
        val = [val stringByReplacingOccurrencesOfString:@")" withString:@""];
        
        NSArray *zlist = [val componentsSeparatedByString:@","];
        if (zlist.count >= 3)
        {
            color = [UIColor colorWithRed:[zlist[0] doubleValue]/255.0 green:[zlist[1] doubleValue]/255.0 blue:[zlist[2] doubleValue]/255.0 alpha:zlist.count>3?[zlist[3] doubleValue]:1];
        }
    }
    
    return color;
}
 
 
+ (NSMutableArray <NSMutableDictionary *>*)stylesFromElement:(TFHppleElement *)e
{
    NSString *b = [e content];
    NSArray <TFHppleElement *> *child = [e children];
    NSMutableArray *attributesList = [NSMutableArray arrayWithCapacity:0];
    
    [child enumerateObjectsUsingBlock:^(TFHppleElement * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (![obj isTextNode])
        {
            /*企管只关注CSS样式中的color,backgroudColor,fontSize这三个属性,其余根据后期要求再解析展示
            CSS对于样式的定义为:color:orange,font-size:16px,background-color:xxx
             */
            NSDictionary *attrMap = [obj attributes];
            [attrMap enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop)
            {
                if (obj && [obj isKindOfClass:[NSString class]])
                {
                    NSArray *plist = [obj componentsSeparatedByString:@","];
                    [plist enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
                    {
                        NSArray *xlist = [obj componentsSeparatedByString:@":"];
                        if ([xlist.firstObject isEqualToString:@"color"])
                        {
                            NSString *val = [[xlist lastObject] uppercaseString];
                            UIColor *color = [CSSStyleMap colorFromCssText:val];
                            if (color)
                            {
                                [attributesList addObject:@{@"fontColor":color,@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
                            }
                        }
                        else if ([xlist.firstObject isEqualToString:@"background-color"])
                        {
                            NSString *val = [[xlist lastObject] uppercaseString];
                            UIColor *color = [CSSStyleMap colorFromCssText:val];
                            if (color)
                            {
                                [attributesList addObject:@{@"backgroundColor":color,@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
                            }
                        }
                        else if ([xlist.firstObject isEqualToString:@"font-size"])
                        {
                            NSInteger val = [[xlist lastObject] integerValue];
                            [attributesList addObject:@{@"fontSize":intToStr(val),@"range":[NSValue valueWithRange:NSMakeRange(0, b.length)]}];
                        }
                    }];
                }
                
            }];
        }
    }];
    
    return attributesList;
}
#endif
@end

页面使用:

javascript 复制代码
NSData *tdata = [cnt dataUsingEncoding:NSUTF8StringEncoding];
TFHpple *doc = [[TFHpple alloc] initWithHTMLData:tdata];
TFHppleElement *e = [[doc searchWithXPathQuery:@"//b"] firstObject];
 
//包含解析出来的样式数据列表
NSMutableArray <NSMutableDictionary *>*styleList = [CSSStyleMap stylesFromElement:e];
javascript 复制代码
//加粗
NSMutableArray <NSValue *>*btagList = [rMap arrayForKey:@"bTag"];
//a标签,跳转
NSMutableArray <NSDictionary *>*atagList = [rMap arrayForKey:@"aTag"];
//CSS样式
NSMutableArray <NSDictionary *>*styleList = [rMap arrayForKey:@"style"];
 
//textView是定义的UITextView的实例对象
 
NSMutableAttributedString *mtext = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
NSString *textStr = mtext.string;
//        NSArray *ranges = [self mutableRangeOfString:@"®[^\\s]+" targetString:textStr];
 
 
[btagList enumerateObjectsUsingBlock:^(NSValue *a, NSUInteger idx, BOOL * _Nonnull stop)
{
    [mtext addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:imTextFont(16)] range:a.rangeValue];
}];
 
[atagList enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
{
    NSRange range = [(NSValue *)[obj objectForKey:@"range"] rangeValue];
    [mtext addAttribute:NSForegroundColorAttributeName value:[UIColor colorFromHex:@"#0000ee"] range:range];
    
    [mtext addAttribute:NSLinkTag value:[obj stringForKey:@"href"] range:range];
}];
 
[styleList enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
{
    UIColor *fcolor = [obj objectForKey:@"fontColor"];
    NSRange range = [(NSValue *)[obj objectForKey:@"range"] rangeValue];
    [mtext addAttribute:NSForegroundColorAttributeName value:fcolor range:range];
}];
 
[textView setAttributedText:mtext];

这个示例只是展示其中一部分逻辑,你可以进行二次开发,扩展其功能,支持更多的属性的展示!

对了,肯定会有人说使用Webview直接加载就行了嘛,兄弟,我使用的场景是会话页面,你使用webview加载,就会存在性能体验问题!如果你全页面只有一个这样的消息,当然首选就是Webview,而我的页面如下,就不得不考虑用户体验!

相关推荐
y先森30 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy30 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891133 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐4 小时前
前端图像处理(一)
前端