web-dev-qa-db-fra.com

Comment changer la couleur de overscroll Edge et de la lueur de overscroll

Comment changer la couleur de surligner Edge et lueur de sur-défilement ou comment changer la couleur blanche (couleur par défaut) d'Android version 5.0 Lollipop?

27
Ad Dahoun

La couleur de lueur de défilement hérite de la valeur de couleur primaire définie par Android:colorPrimary dans l'ensemble de votre application. Mais si vous devez spécifier une valeur différente, utilisez simplement Android:colorEdgeEffect.

<style name="MyAppTheme" parent="***">
   <item name="Android:colorEdgeEffect">@color/my_color</item>
</style>
50
Ahmed Hegazy

Sur Lollipop la lueur de contour hérite de colorPrimary. Une fois la vue créée, la couleur de lueur Edge ne peut être modifiée que par réflexion. Cela peut être utile lorsque vous chargez des couleurs de manière dynamique à l'aide de Palette.

EDIT: TL; DR: Téléchargez la classe entière à partir d’ici: https://github.com/consp1racy/Android-commons/blob/master/commons/src/main/Java/net/ xpece/Android/widget/XpEdgeEffect.Java

PROGUARD SETUP: Si vous voulez utiliser ceci sur des widgets de la bibliothèque de support, vous devez conserver les noms de champs. Le moyen le plus rapide de le faire est le suivant (bien que toujours inutile):

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

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

Créez une classe d'utilitaire avec le code suivant:

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();
    }
  }
}
24
Eugen Pechanec

Si vous utilisez la dernière implémentation de RecyclerView, il est assez simple de changer la couleur de débordement par programmation. Utilisez le code suivant (implémentation de Kotlin):

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

Notez que cela ne fonctionne que pour l'API de niveau 21 (Lollipop) et supérieur. Si vous connaissez la valeur au moment de la compilation, utilisez la variable colorEdgeEffect, comme l'a souligné Ahmed.

8
Phoca

Dans les pré-Lollipop, l’effet de luminescence est en fait un dessin incorporable dans les ressources du système d’exploitation, vous pouvez appliquer un ColorFilter à ce sujet:

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) {
    }
}

L'appeler une fois dans onCreate est suffisant.

changeOverScrollGlowColor(getResources(), R.color.colorPrimary);
1
John