Steven Schoen
Steven Schoen

Reputation: 4386

Custom overscroll glow/edge color for ListView?

I have a ListView, and a custom style that basically looks just like Holo, but with yellow accents instead of blue.

When I scroll to the bottom or top of the list, I get the un-fitting blue. I made custom drawables for overscroll_glow.png and overscroll_edge.png, but I don't know how to use them.

How can I get my ListView to use these drawables instead of the system ones?

Would the OverScroller class help?

Upvotes: 10

Views: 13963

Answers (6)

bapho
bapho

Reputation: 936

Please don't forget to change the overscroll edge line:

        final int edgeDrawableId = res.getIdentifier("overscroll_edge", "drawable", "android");
        final Drawable overscrollEdge = res.getDrawable(edgeDrawableId);
        overscrollEdge.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);

Upvotes: 3

toni
toni

Reputation: 1684

Here you are the solution:

public static void ChangeEdgeEffect(Context cxt, View list, int color){

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

        EdgeEffect edgeEffectTop = new EdgeEffect(cxt);
        edgeEffectTop.setColor(color);
        EdgeEffect edgeEffectBottom = new EdgeEffect(cxt);
        edgeEffectBottom.setColor(color);

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

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

    }else{
        int glowDrawableId = cxt.getResources().getIdentifier("overscroll_glow", "drawable", "android");
        Drawable androidGlow = cxt.getResources().getDrawable(glowDrawableId);
        assert androidGlow != null;
        androidGlow.setColorFilter(cxt.getResources().getColor(color), PorterDuff.Mode.SRC_ATOP);
    }
}

Upvotes: 3

MariusBudin
MariusBudin

Reputation: 1287

I add this answer because this is one of the top results on the topic and the top answer is not correct anymore. Well, it actually is for pre-lollipop versions but as expected, when you use java reflection you get bitten back, and that's what happened, if you use the code

int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
androidGlow.setColorFilter(context.getResources().getColor(R.color.gm_color), PorterDuff.Mode.MULTIPLY);

this will crash in Lollipop + devices because that resource is not there anymore. So for android 5.+ you should use:

       <item name="android:colorEdgeEffect">@color/custom_color</item>

in your theme, overriden in a values-v21/themes.xml file if you are not targeting min 21 version

Upvotes: 0

Menny
Menny

Reputation: 473

You can use a reflection-like solution to hack your way to changing this glow color:

int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
androidGlow.setColorFilter(brandColor, PorterDuff.Mode.MULTIPLY);

I encountered the same problem, and it seems like a good solution, at least until Google adds an API for changing the color (or branding the color): http://evendanan.net/android/branding/2013/12/09/branding-edge-effect/

Upvotes: 8

MinceMan
MinceMan

Reputation: 7592

Just use this library. I've only had a problem with wrapping context on a popup menu in landscape on a device that doesn't have overscroll (HTC One X/Sense 4.5). Works like a charm!

https://github.com/AndroidAlliance/EdgeEffectOverride

Upvotes: 5

heycosmo
heycosmo

Reputation: 1388

tried this? setOverscrollFooter(Drawable)?

Update 1:

Oops. Nevermind. You've probably already seen this discussion.

The glow behavior is wrapped in the EdgeEffect class. You could disable the default edge effects by calling setOverScrollMode(OVER_SCROLL_NEVER) on your ListView and then rolling your own EdgeEffect class (the details of which are beyond me at this point).

Update 2:

Ouch. The calls on the EdgeEffect object created within AbsListView are buried deep within the scrolling logic. Could be tough. An easy fix would be a feature request to the Android team for a setEdgeEffect(EdgeEffect) method in AbsListView...

Upvotes: 4

Related Questions