如何在Android Lollipop中添加ScrollView边缘颜色效果?

19

在我的应用程序中,我通过以下方式更改页面超出滚动时的发光效果颜色:

int glowDrawableId = contexto.getResources().getIdentifier("overscroll_glow", "drawable", "android");
Drawable androidGlow = contexto.getResources().getDrawable(glowDrawableId);
assert androidGlow != null;
androidGlow.setColorFilter(getResources().getColor(R.color.MyColor), PorterDuff.Mode.SRC_ATOP);
但是当我升级到Lollipop版本时,这段代码会崩溃。我得到以下错误代码:
FATAL EXCEPTION: main
Process: com.myproject.myapp, PID: 954
android.content.res.Resources$NotFoundException: Resource ID #0x0
at android.content.res.Resources.getValue(Resources.java:1233)
at android.content.res.Resources.getDrawable(Resources.java:756)
at android.content.res.Resources.getDrawable(Resources.java:724)

看起来lollipop中缺少overscroll_glow资源。

我该怎么做才能实现它?


1
通常情况下,您不应该尝试引用框架私有资源。这些资源不能保证在操作系统更新或不同OEM定制版本的操作系统之间持久存在。 - alanv
6个回答

52

您可以在主题中指定android:colorEdgeEffect来更改整个应用程序中的超滚动发光颜色。默认情况下,这将继承android:colorPrimary设置的主要颜色值。

res/values/themes.xml:

<style name="MyAppTheme" parent="...">
    ...
    <item name="android:colorEdgeEffect">@color/my_color</item>
</style>

你可以使用内联主题覆盖来修改单个视图的值。

res/values/themes.xml:

<!-- Note that there is no parent style or additional attributes specified. -->
<style name="MyEdgeOverlayTheme">
    <item name="android:colorEdgeEffect">@color/my_color</item>
</style>

res/layout/my_layout.xml:

<ListView
    ...
    android:theme="@style/MyEdgeOverlayTheme" />

使用该方法时,我遇到了以下错误。错误:(6, 21)找不到与给定名称相匹配的资源:attr 'colorEdgeEffect'。 - user1506630
1
抱歉,应该是android:colorEdgeEffect。 - alanv
1
@alanv 你知道如何通过编程的方式改变发光颜色吗?在我的应用程序中,我根据上下文编程地更改状态栏和工具栏颜色,如果能够改变过度滚动发光颜色也会很好。我发现Lollipop中的新联系人应用程序会根据联系人而改变。 - MrBrightside
如果你想使用标准小部件,可以通过反射实现...请参见 http://stackoverflow.com/a/27451249/82788(答案的第二部分,虽然丑陋但有效)。如果您有自定义小部件,则可以使用自定义的 EdgeEffect,它不会那么混乱。 - matiash

11

"android:colorEdgeEffect" 解决方案完美地工作,并且比之前的 hack 要好得多。然而,如果需要在程序中动态更改边缘颜色,则无法使用此解决方案。

不过,可以使用反射来直接设置 AbsListViewScrollView 实例中的 EdgeEffect 对象。例如:

EdgeEffect edgeEffectTop = new EdgeEffect(this);
edgeEffectTop.setColor(Color.RED);

EdgeEffect edgeEffectBottom = new EdgeEffect(this);
edgeEffectBottom.setColor(Color.RED);

try {
    Field f1 = AbsListView.class.getDeclaredField("mEdgeGlowTop");
    f1.setAccessible(true);
    f1.set(listView, edgeEffectTop);

    Field f2 = AbsListView.class.getDeclaredField("mEdgeGlowBottom");
    f2.setAccessible(true);
    f2.set(listView, edgeEffectBottom);
} catch (Exception e) {
    e.printStackTrace();
}

EdgeEffect.setColor()在Lollipop中被添加。

然而,与任何基于反射的解决方案一样,需要注意相同的警告。


4
在棒棒糖版本中,可以使用项目样式colorPrimary来自定义超出滚动效果的颜色:
<style name="MyApp" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/mycolor</item>
</style>

这个项目还会影响工具栏的颜色。


2

我正在使用这个方法在Android L上通过编程方式更改边缘颜色。这适用于listView和scrollView,以及继承它们的视图。

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void setEdgeEffectL(View scrollableView, int color) {
    final String[] edgeGlows = {"mEdgeGlowTop", "mEdgeGlowBottom", "mEdgeGlowLeft", "mEdgeGlowRight"};
    for (String edgeGlow : edgeGlows) {
        Class<?> clazz = scrollableView.getClass();
        while (clazz != null) {
            try {
                final Field edgeGlowField = clazz.getDeclaredField(edgeGlow);
                edgeGlowField.setAccessible(true);
                final EdgeEffect edgeEffect = (EdgeEffect) edgeGlowField.get(scrollableView);
                edgeEffect.setColor(color);
                break;
            } catch (Exception e) {
                clazz = clazz.getSuperclass();
            }
        }
    }
}

1

overscroll_glow.png在21平台中不存在。您可以从20平台复制资源并使用它们。

您可以在以下位置找到overscroll_glow.png

{SDK_FOLDER}\platforms\android-20\data\res

这样您就不需要使用反射,避免在某些更新后影响您的程序。


0

我知道我来晚了,但这对我的应用程序API>=17有效:

<style name="ListTheme" parent="Theme.AppCompat.Light.DarkActionBar">
      <item name="colorPrimary">@color/colorPrimaryDark</item>
</style>

<ListView   
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ListTheme"/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接