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)

总结

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

相关推荐
Digitally20 分钟前
如何将文件从 iPhone 传输到 Android(新指南)
android·ios·iphone
whysqwhw1 小时前
OkHttp深度架构缺陷分析与演进规划
android
用户7093722538511 小时前
Android14 SystemUI NotificationShadeWindowView 加载显示过程
android
木叶丸2 小时前
跨平台方案该如何选择?
android·前端·ios
顾林海3 小时前
Android ClassLoader加载机制详解
android·面试·源码
用户2018792831673 小时前
🎨 童话:Android画布王国的奇妙冒险
android
whysqwhw3 小时前
OkHttp框架的全面深入架构分析
android
你过来啊你3 小时前
Android App冷启动流程详解
android
泓博4 小时前
KMP(Kotlin Multiplatform)改造(Android/iOS)老项目
android·ios·kotlin
移动开发者1号4 小时前
使用Baseline Profile提升Android应用启动速度的终极指南
android·kotlin