How to change the color of overscroll edge and ove

2019-01-25 02:07发布

How to Change color of over-scroll edge and over-scroll glow or how to change the white color (default color) of android release 5.0 lollipop?

4条回答
对你真心纯属浪费
2楼-- · 2019-01-25 02:40

On LOLLIPOP the edge glow inherits from colorPrimary. After the view is created the edge glow color can only be changed through reflection. This can be useful when you load colors dynamically using Palette.

EDIT: TL;DR: Download the whole class from here: https://github.com/consp1racy/android-commons/blob/master/commons/src/main/java/net/xpece/android/widget/XpEdgeEffect.java

PROGUARD SETUP: If you're going to use this on widgets from support library you need to keep the field names. Quickest way to do it is the following (although still wasteful):

-keepclassmembers class * extends android.view.View {
    <fields>;    
}

-keepclassmembers class android.support.v4.widget.EdgeEffectCompat {
    <fields>;    
}

Create a utility class with the following code:

private static final Class<?> CLASS_SCROLL_VIEW = ScrollView.class;
private static final Field SCROLL_VIEW_FIELD_EDGE_GLOW_TOP;
private static final Field SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM;

private static final Class<?> CLASS_LIST_VIEW = AbsListView.class;
private static final Field LIST_VIEW_FIELD_EDGE_GLOW_TOP;
private static final Field LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM;

static {
  Field edgeGlowTop = null, edgeGlowBottom = null;

  for (Field f : CLASS_SCROLL_VIEW.getDeclaredFields()) {
    switch (f.getName()) {
      case "mEdgeGlowTop":
        f.setAccessible(true);
        edgeGlowTop = f;
        break;
      case "mEdgeGlowBottom":
        f.setAccessible(true);
        edgeGlowBottom = f;
        break;
    }
  }

  SCROLL_VIEW_FIELD_EDGE_GLOW_TOP = edgeGlowTop;
  SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM = edgeGlowBottom;

  for (Field f : CLASS_LIST_VIEW.getDeclaredFields()) {
    switch (f.getName()) {
      case "mEdgeGlowTop":
        f.setAccessible(true);
        edgeGlowTop = f;
        break;
      case "mEdgeGlowBottom":
        f.setAccessible(true);
        edgeGlowBottom = f;
        break;
    }
  }

  LIST_VIEW_FIELD_EDGE_GLOW_TOP = edgeGlowTop;
  LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM = edgeGlowBottom;
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setEdgeGlowColor(AbsListView listView, int color) {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    try {
      EdgeEffect ee;
      ee = (EdgeEffect) LIST_VIEW_FIELD_EDGE_GLOW_TOP.get(listView);
      ee.setColor(color);
      ee = (EdgeEffect) LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(listView);
      ee.setColor(color);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setEdgeGlowColor(ScrollView scrollView, int color) {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    try {
      EdgeEffect ee;
      ee = (EdgeEffect) SCROLL_VIEW_FIELD_EDGE_GLOW_TOP.get(scrollView);
      ee.setColor(color);
      ee = (EdgeEffect) SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(scrollView);
      ee.setColor(color);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}
查看更多
对你真心纯属浪费
3楼-- · 2019-01-25 02:55

In pre-lollipop the glow effect is actually a Drawable embedded in the OS's resources, you can apply a ColorFilter on that:

public static void changeOverScrollGlowColor(Resources res, int colorID ) {
    try {
        final int glowDrawableId = res.getIdentifier("overscroll_glow", "drawable", "android");
        final Drawable overscrollGlow = res.getDrawable(glowDrawableId);
        overscrollGlow.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);

        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);
    } catch (Exception ignored) {
    }
}

Calling it once in onCreate is enough.

changeOverScrollGlowColor(getResources(), R.color.colorPrimary);
查看更多
欢心
4楼-- · 2019-01-25 02:58

The overscroll glow color inherits the primary color value set by android:colorPrimary in your entire app. But If you need to specify different value simply use android:colorEdgeEffect.

<style name="MyAppTheme" parent="***">
   <item name="android:colorEdgeEffect">@color/my_color</item>
</style>
查看更多
三岁会撩人
5楼-- · 2019-01-25 02:59

If you're using the latest RecyclerView implementation it is pretty straightforward to change the overflow colour programmatically. Use the following code (Kotlin implementation):

recyclerView.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
    override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect {
        return EdgeEffect(view.context).apply { setColor(color) }
    }
}

Note that this works only for API level 21 (Lollipop) and above. If you know the value at compile time, use the colorEdgeEffect as pointed out by Ahmed.

查看更多
登录 后发表回答