Как изменить цвет края прокрутки и свечения
Как изменить цвет края с чрезмерной прокруткой и свечения с избыточной прокруткой или как изменить белый цвет (цвет по умолчанию) для леденца на палочке Android версии 5.0?
4 ответа
Цвет свечения с прокруткой наследует значение основного цвета, установленное android:colorPrimary
во всем приложении. Но если вам нужно указать другое значение, просто используйте android:colorEdgeEffect
,
<style name="MyAppTheme" parent="***">
<item name="android:colorEdgeEffect">@color/my_color</item>
</style>
На LOLLIPOP
сияние края наследуется от colorPrimary
, После создания вида цвет свечения краев можно изменить только с помощью отражения. Это может быть полезно, когда вы загружаете цвета динамически, используя Palette
,
РЕДАКТИРОВАТЬ: TL;DR: Скачать весь класс отсюда: https://github.com/consp1racy/android-commons/blob/master/commons/src/main/java/net/xpece/android/widget/XpEdgeEffect.java
НАСТРОЙКА PROGUARD: Если вы собираетесь использовать это на виджетах из библиотеки поддержки, вам нужно сохранить имена полей. Самый быстрый способ сделать это заключается в следующем (хотя все еще расточительно):
-keepclassmembers class * extends android.view.View {
<fields>;
}
-keepclassmembers class android.support.v4.widget.EdgeEffectCompat {
<fields>;
}
Создайте служебный класс со следующим кодом:
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();
}
}
}
Если вы используете новейшую реализацию RecyclerView, довольно просто программно изменить цвет переполнения. Используйте следующий код (реализация Kotlin):
recyclerView.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect {
return EdgeEffect(view.context).apply { setColor(color) }
}
}
Обратите внимание, что это работает только для API уровня 21 (Lollipop) и выше. Если вы знаете значение во время компиляции, используйте colorEdgeEffect
как указал Ахмед.
В pre-lollipop эффект свечения фактически является Drawable, встроенным в ресурсы ОС, к нему можно применить ColorFilter:
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) {
}
}
Достаточно вызвать его один раз в onCreate.
changeOverScrollGlowColor(getResources(), R.color.colorPrimary);