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)

总结

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

相关推荐
xiangpanf27 分钟前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx3 小时前
安卓线程相关
android
消失的旧时光-19434 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon5 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon5 小时前
VSYNC 信号完整流程2
android
dalancon5 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013846 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android6 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才7 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶8 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle