1 关键字

Button; backgroundColor

2 问题描述

2.1 运行环境

系统版本:3.2Release
开发板:rk3568

2.2 问题现象:

Button组件设置为非法颜色值时按钮显示为透明背景色

Button("click").backgroundColor('##678').width(100).height(30) //展示为透明背景色的按钮
Button("click").backgroundColor('yellow').width(100).height(30) //展示为透明背景色的按钮
Button("click").backgroundColor('red').width(100).height(30) //展示为背景为红色的按钮

3 问题原因

3.1 正常机制

Button组件未设置背景色或设置为非法颜色值时按钮背景显示为默认的主题颜色(蓝色)

3.2 异常机制

Button组件设置为非法颜色值时按钮背景显示为透明背景色

4 解决方案

修改JSButton::JsBackgroundColor(const JSCallbackInfo& info) 方法(文件路径:\foundation\arkui\ace_engine\frameworks\bridge\declarative_frontend\jsview\js_button.cpp):

void JSButton::JsBackgroundColor(const JSCallbackInfo& info)
{
    if (Container::IsCurrentUseNewPipeline()) {

        JSViewAbstract::JsBackgroundColor(info);   // 删除此行     

        if (!ParseJsColor(info[0], backgroundColor)) { // 增加此行   
           auto buttonTheme = GetTheme<ButtonTheme>();  // 增加此行   
            if (buttonTheme) { // 增加此行   
               backgroundColor = buttonTheme->GetBgColor(); // 增加此行   
           } // 增加此行   
         } // 增加此行   
        ViewAbstractModel::GetInstance()->SetBackgroundColor(backgroundColor); // 增加此行   

        return;
    }
}

5 定位过程

设置Button背景色入口函数为JSButton::JsBackgroundColor(js_button.cpp)

void JSButton::JsBackgroundColor(const JSCallbackInfo& info)
{
    if (Container::IsCurrentUseNewPipeline()) {
        JSViewAbstract::JsBackgroundColor(info);   

Arkui NG框架下,执行JSViewAbstract::JsBackgroundColor(info);

void JSViewAbstract::JsBackgroundColor(const JSCallbackInfo& info)
{
    if (info.Length() < 1) {
        LOGE("The argv is wrong, it is supposed to have at least 1 argument");
        return;
    }
    Color backgroundColor;
    if (!ParseJsColor(info[0], backgroundColor)) { //由ParseJsColor解析颜色值,若无法解析则返回 Color::TRANSPARENT
        backgroundColor = Color::TRANSPARENT;
    }

    ViewAbstractModel::GetInstance()->SetBackgroundColor(backgroundColor); //设置背景色
}

ParseJsColor方法解析颜色值:

bool Color::ParseColorString(std::string colorStr, Color& color, uint32_t maskAlpha)
{
    ...
    // Remove all " ".
    colorStr.erase(std::remove(colorStr.begin(), colorStr.end(), ' '), colorStr.end());

    return (MatchColorWithMagic(colorStr, maskAlpha, color) || MatchColorWithMagicMini(colorStr, maskAlpha, color) ||
            MatchColorWithRGB(colorStr, color) || MatchColorWithRGBA(colorStr, color) ||
            MatchColorSpecialString(colorStr, color) || ParseUintColorString(colorStr, color));
}

具体的可解析颜色值有以下:

  • MatchColorWithMagic :例如: #55667700
  • MatchColorWithMagicMini :例如: #567
  • MatchColorWithRGB: 例如:rgb(90,254,180).
  • MatchColorWithRGBA: 例如:rgba(90,254,180,0.5)
  • MatchColorSpecialString 特殊颜色值,支持的颜色(共6个)以及对应色值相关定义源码如下(foundation\arkui\ace_engine\frameworks\core\components\common\properties\color.cpp):
    static const LinearMapNode<Color> colorTable[] = {
        { "black", Color(0xff000000) },
        { "blue", Color(0xff0000ff) },
        { "gray", Color(0xffc0c0c0) },
        { "green", Color(0xff00ff00) },
        { "red", Color(0xffff0000) },
        { "white", Color(0xffffffff) },
    };

所以,像"yellow","##678"这类字符 Color::ParseColorString无法解析到具体颜色值,backgroundColor 被设置为 Color::TRANSPARENT。

6 知识分享

颜色值有多种表示方法,不同格式可以相互转换,其中RGBA的形式的A代表alpha通道,用作不透明度参数。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐