Custom overscroll glow/edge color for ListView?
Asked Answered
C

6

10

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?

Cark answered 24/8, 2012 at 1:23 Comment(0)
H
8

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/

Hague answered 9/12, 2013 at 19:22 Comment(4)
Multiply isn't good because it will mix your color witht the default blue. You should use SrcAtop. It will completelly replace the old color.Renie
Where does one call this code as far as ScrollView is concerned?Baba
Hey Menny thanks for the post I can't seem to get this to work I have context set like this Context context = this;Maegan
Here is a working code: gist.github.com/menny/7878762#file-brandgloweffect_full-javaHague
L
5

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

Longfellow answered 2/8, 2013 at 21:18 Comment(0)
T
4

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...

Tousle answered 24/8, 2012 at 1:39 Comment(2)
Tried the footer, wasn't what I needed. So the only way for me to do it would be to create a custom AbsListView class? Too hacky for my liking :(Cark
Well, I'm now convinced that it could be done by subclassing ListView and overriding a slew of methods (onOverScrolled() being the important one), but I'm not sure it's worth it. :(Tousle
G
3

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);
    }
}
Giant answered 11/2, 2015 at 9:23 Comment(0)
R
3

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);
Resolve answered 25/3, 2015 at 14:23 Comment(0)
Z
0

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

Zebedee answered 22/1, 2015 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.