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)

总结

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

相关推荐
雾里看山1 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql
水瓶丫头站住10 小时前
安卓APP如何适配不同的手机分辨率
android·智能手机
xvch10 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
xvch14 小时前
Kotlin 2.1.0 入门教程(七)
android·kotlin
望风的懒蜗牛14 小时前
编译Android平台使用的FFmpeg库
android
浩宇软件开发15 小时前
Android开发,待办事项提醒App的设计与实现(个人中心页)
android·android studio·android开发
ac-er888815 小时前
Yii框架中的多语言支持:如何实现国际化
android·开发语言·php
苏金标16 小时前
The maximum compatible Gradle JVM version is 17.
android
zhangphil16 小时前
Android BitmapShader简洁实现马赛克,Kotlin(一)
android·kotlin
iofomo21 小时前
Android平台从上到下,无需ROOT/解锁/刷机,应用级拦截框架的最后一环,SVC系统调用拦截。
android