MD3——SearchView自定义背景

MD3------SearchView自定义背景

MD3 - SearchView

介绍

官方描述:

SearchView组件提供了一个全屏搜索视图的实现,该视图可用于显示返回导航、搜索提示和文本、菜单项以及搜索建议和结果。它还带有一个清晰的文本按钮,根据用户是否输入文本显示和隐藏。

效果如下:

可用属性如下:

Element Attribute Related method(s) Default value
Search text appearance android:textAppearance setTextAppearance getTextAppearance @style/TextAppearance.Material3.SearchBar
Search text android:text setText getText null
Search hint android:hint setHint getHint null
Color app:backgroundTint -- ?attr/colorSurfaceContainerHigh
Flag for navigation icon app:hideNavigationIcon -- true
Flag for DrawerArrowDrawable app:useDrawerArrowDrawable -- false
Flag for soft keyboard app:autoShowKeyboard -- true

需求

需要修改这个背景色,并且是动态修改。尝试过修改app:backgroundTint ,但是不起作用,所以在SearchView里翻呀翻,最后也算是找到了解决办法。

分析SearchVIew

可以看到SearchView里有一个backgroundView,不难知道这个就是我们需要修改颜色的View

java 复制代码
// SearchView

...
final View backgroundView;

...

// 修改颜色的地方
private void setUpBackgroundViewElevationOverlay(float elevation) {
    if (elevationOverlayProvider == null || backgroundView == null) {
        return;
    }
    int backgroundColor =
            elevationOverlayProvider.compositeOverlayWithThemeSurfaceColorIfNeeded(elevation);
    backgroundView.setBackgroundColor(backgroundColor);
}

找到地方就好办了,直接拷贝一个SearchView,然后改成自己想要的颜色即可

看下效果:

改进

虽然成功改了颜色,但是和原来效果不一样呀,原来的颜色是基于colorPrimary的,并且也不是这样的纯色,对比下之前的:

可以看到似乎是colorPrimary的颜色叠加了白色,那我们就继续看SearchView,可以知道颜色处理肯定是在这行代码:

java 复制代码
int backgroundColor =
            elevationOverlayProvider.compositeOverlayWithThemeSurfaceColorIfNeeded(elevation);

那就继续看这个方法的实现:

java 复制代码
// ElevationOverlayProvider

...

// 看到这个colorSurface就知道他的颜色是白/黑
// 根据主题变换,证实了之前的猜想
  @ColorInt
  public int compositeOverlayWithThemeSurfaceColorIfNeeded(float elevation) {
    return compositeOverlayIfNeeded(colorSurface, elevation);
  }

  ...

@ColorInt
public int compositeOverlayIfNeeded(@ColorInt int backgroundColor, float elevation) {
    if (elevationOverlayEnabled && isThemeSurfaceColor(backgroundColor)) {
        return compositeOverlay(backgroundColor, elevation);
    } else {
        return backgroundColor;
    }
}

...

// 关键代码实现
@ColorInt
public int compositeOverlay(@ColorInt int backgroundColor, float elevation) {
    float overlayAlphaFraction = calculateOverlayAlphaFraction(elevation);
    int backgroundAlpha = Color.alpha(backgroundColor);
    int backgroundColorOpaque = ColorUtils.setAlphaComponent(backgroundColor, 255);
    int overlayColorOpaque =
        MaterialColors.layer(backgroundColorOpaque, elevationOverlayColor, overlayAlphaFraction);
    if (overlayAlphaFraction > 0 && elevationOverlayAccentColor != Color.TRANSPARENT) {
        int overlayAccentColor =
            ColorUtils.setAlphaComponent(elevationOverlayAccentColor, OVERLAY_ACCENT_COLOR_ALPHA);
        overlayColorOpaque = MaterialColors.layer(overlayColorOpaque, overlayAccentColor);
    }
    return ColorUtils.setAlphaComponent(overlayColorOpaque, backgroundAlpha);
}

这里的elevationOverlayColorelevationOverlayAccentColor默认是和colorPrimary是同色,到这里就已经知道如何修改颜色了,具体内部做了什么计算就不管了,在我们的SearchView里添加一个修改背景色的方法,把上面compositeOverlay方法的关键实现拷贝过来:

java 复制代码
public void setBackgroundViewColor(@ColorInt int color) {
    int backgroundColor = MaterialColors.getColor(getContext(), R.attr.colorSurface, Color.WHITE);
    float elevation = getOverlayElevation();
    float overlayAlphaFraction = elevationOverlayProvider.calculateOverlayAlphaFraction(elevation);
    int backgroundAlpha = Color.alpha(backgroundColor);
    int backgroundColorOpaque = ColorUtils.setAlphaComponent(backgroundColor, 255);
    int overlayColorOpaque =
            MaterialColors.layer(backgroundColorOpaque, color, overlayAlphaFraction);
    if (overlayAlphaFraction > 0 && color != Color.TRANSPARENT) {
        int overlayAccentColor =
                ColorUtils.setAlphaComponent(color, (int) Math.round(0.02 * 255));
        overlayColorOpaque = MaterialColors.layer(overlayColorOpaque, overlayAccentColor);
    }
    int overlayColor = ColorUtils.setAlphaComponent(overlayColorOpaque, backgroundAlpha);
    backgroundView.setBackgroundColor(overlayColor);
}

// 调用(kotlin)
binding.colorSearchView.setBackgroundViewColor(themeColor)

这里要注意: elevationOverlayColorelevationOverlayAccentColor替换成我们需要设置的颜色(color),原因前面分析过了哈。如果需要让颜色更深一点,可以修改elevation的值,看看效果吧:

补充:如何需要设置背景图片也是可以的

java 复制代码
backgroundView.setBackgroundResource(int resid)

总结

为了改这个,网上一顿查,愣是没找到解决办法,还好解决了,不然我可能直接强行改成黑白了

相关推荐
2501_9327502642 分钟前
Android 跑马灯:从一行 XML 到自定义控件
android
BoomHe13 小时前
Android Framework 文件应用移植到 AndroidStudio
android
传奇开心果编程14 小时前
【Jetpack Compose基础语法学与练】第8课 rememberSaveable,页面旋转/系统重建保留状态
android·学习·ui·kotlin·android jetpack
>Andre<14 小时前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件
事圆则缓15 小时前
Java 8 Lambda、Stream、Optional 与 Android 边界:从回调语法到运行时兼容
android·java
mmsx15 小时前
Android 地图十万要素不卡顿:空间网格 + 渐进式加载的移动端实践
android·大数据·opengl
Godikov17 小时前
Android 工业终端保活实战:前台服务 + 开机自启 + 更新自启的三重保障
android
字节暗面17 小时前
SO加固强度怎么量化?腾讯ACE与FairGuard静态分析实测
android·逆向
终端安全笔记19 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
字节暗面19 小时前
一次游戏安全SO静态分析记录:腾讯ACE与FairGuard加固强度对比
android·逆向工程·游戏加固