package com.simplecity.amp_library.utils; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.content.SharedPreferences; import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LightingColorFilter; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.NinePatchDrawable; import android.os.Build; import android.preference.PreferenceManager; import android.support.annotation.ColorInt; import android.support.annotation.IntDef; import android.support.design.widget.TextInputLayout; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.util.StateSet; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.EdgeEffect; import android.widget.EditText; import android.widget.ImageView; import android.widget.ScrollView; import android.widget.TextView; import com.doomonafireball.betterpickers.hmspicker.HmsPicker; import com.doomonafireball.betterpickers.hmspicker.HmsView; import com.readystatesoftware.systembartint.SystemBarTintManager; import com.simplecity.amp_library.R; import com.simplecity.amp_library.ui.activities.MainActivity; import com.simplecity.amp_library.ui.activities.PlayerActivity; import com.simplecity.amp_library.ui.activities.WidgetConfigureExtraLarge; import com.simplecity.amp_library.ui.activities.WidgetConfigureLarge; import com.simplecity.amp_library.ui.activities.WidgetConfigureMedium; import com.simplecity.amp_library.ui.activities.WidgetConfigureSmall; import com.simplecity.amp_library.ui.views.FilterableStateListDrawable; import com.simplecity.amp_library.ui.views.SizableSeekBar; import com.simplecity.amp_library.ui.views.SlidingTabLayout; import com.simplecity.amp_library.ui.views.Themable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ThemeUtils { private static final String TAG = "ThemeUtils"; private static ThemeUtils sInstance; @Retention(RetentionPolicy.SOURCE) @IntDef({WHITE, BLACK}) public @interface ThemeColor { } public static final int WHITE = 0; public static final int BLACK = 1; @Retention(RetentionPolicy.SOURCE) @IntDef({ThemeType.TYPE_LIGHT, ThemeType.TYPE_DARK, ThemeType.TYPE_BLACK, ThemeType.TYPE_SOLID_LIGHT, ThemeType.TYPE_SOLID_DARK, ThemeType.TYPE_SOLID_BLACK}) public @interface ThemeType { int TYPE_LIGHT = 0; int TYPE_DARK = 1; int TYPE_BLACK = 2; int TYPE_SOLID_LIGHT = 3; int TYPE_SOLID_DARK = 4; int TYPE_SOLID_BLACK = 5; } public int themeType; public static ThemeUtils getInstance() { if (sInstance == null) { sInstance = new ThemeUtils(); } return sInstance; } private ThemeUtils() { } /** * @param context the context * @return the current {@link com.simplecity.amp_library.utils.ThemeUtils.ThemeType} */ public static int getThemeType(Context context) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); String theme = sharedPreferences.getString("pref_theme_base", "0"); if (Integer.valueOf(theme) == 0) { return ThemeType.TYPE_SOLID_LIGHT; } else if (Integer.valueOf(theme) == 1) { return ThemeType.TYPE_SOLID_DARK; } else if (Integer.valueOf(theme) == 2) { return ThemeType.TYPE_SOLID_BLACK; } return ThemeType.TYPE_SOLID_LIGHT; } public boolean isThemeDark() { return themeType == ThemeType.TYPE_DARK || themeType == ThemeType.TYPE_SOLID_DARK || themeType == ThemeType.TYPE_BLACK || themeType == ThemeType.TYPE_SOLID_BLACK; } public static void setTheme(Activity activity) { int themeType = getThemeType(activity); ThemeUtils.getInstance().themeType = themeType; if (activity instanceof PlayerActivity) { if (themeType == ThemeType.TYPE_LIGHT || themeType == ThemeType.TYPE_SOLID_LIGHT) { activity.setTheme(R.style.AppTheme_Solid_Light_Transparent_ActionBar); } else if (themeType == ThemeType.TYPE_DARK || themeType == ThemeType.TYPE_SOLID_DARK) { activity.setTheme(R.style.AppTheme_Solid_Dark_Transparent_ActionBar); } else if (themeType == ThemeType.TYPE_BLACK || themeType == ThemeType.TYPE_SOLID_BLACK) { activity.setTheme(R.style.AppTheme_Solid_Black_Transparent_ActionBar); } return; } if (activity instanceof WidgetConfigureMedium || activity instanceof WidgetConfigureExtraLarge || activity instanceof WidgetConfigureLarge || activity instanceof WidgetConfigureSmall) { activity.setTheme(R.style.AppTheme_Widgets); return; } if (themeType == ThemeType.TYPE_LIGHT) { activity.setTheme(R.style.AppTheme_Light); } else if (themeType == ThemeType.TYPE_DARK) { activity.setTheme(R.style.AppTheme_Dark); } else if (themeType == ThemeType.TYPE_SOLID_LIGHT) { activity.setTheme(R.style.AppTheme_Solid_Light); } else if (themeType == ThemeType.TYPE_SOLID_DARK) { activity.setTheme(R.style.AppTheme_Solid_Dark); } else if (themeType == ThemeType.TYPE_BLACK) { activity.setTheme(R.style.AppTheme_Black); } else if (themeType == ThemeType.TYPE_SOLID_BLACK) { activity.setTheme(R.style.AppTheme_Solid_Black); } } @SuppressLint("NewApi") public static Drawable themeActionBar(AppCompatActivity activity) { if (activity == null) { return null; } if (ShuttleUtils.hasLollipop()) { Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.mipmap.ic_launcher); if (bitmap != null) { ActivityManager.TaskDescription td = new ActivityManager.TaskDescription(null, bitmap, ColorUtils.getPrimaryColor()); activity.setTaskDescription(td); bitmap.recycle(); } } if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_LIGHT || ThemeUtils.getInstance().themeType == ThemeType.TYPE_DARK) { activity.getSupportActionBar().setBackgroundDrawable( DrawableUtils.getColoredDrawable(activity, CompatUtils.getDrawableCompat(activity, R.drawable.ab_transparent))); } if (activity instanceof MainActivity || isActionBarSolid(activity)) { ActionBar actionBar = activity.getSupportActionBar(); Drawable actionBarDrawable = DrawableUtils.getColoredDrawable(activity, CompatUtils.getDrawableCompat(activity, R.drawable.action_bar_bg)); actionBar.setBackgroundDrawable(actionBarDrawable); return actionBarDrawable; } return null; } public static boolean isActionBarSolid(Context context) { return getThemeType(context) == ThemeType.TYPE_SOLID_LIGHT || getThemeType(context) == ThemeType.TYPE_SOLID_DARK || getThemeType(context) == ThemeType.TYPE_SOLID_BLACK; } @SuppressLint("NewApi") public static void themeStatusBar(Activity activity, SystemBarTintManager tintManager) { if (ShuttleUtils.hasKitKat()) { if (ShuttleUtils.hasLollipop()) { activity.getWindow().setStatusBarColor(ColorUtils.getPrimaryColorDark(activity)); } else { if (tintManager != null) { tintManager.setStatusBarTintEnabled(true); tintManager.setStatusBarTintColor(ColorUtils.getPrimaryColor()); } } } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public static void themeNavBar(Activity activity, boolean canTheme) { if (!ShuttleUtils.hasLollipop()) { return; } if (canTheme) { activity.getWindow().setNavigationBarColor(ColorUtils.getPrimaryColorDark(activity)); } else { activity.getWindow().setNavigationBarColor(Color.BLACK); } } public static void themeHmsPicker(HmsPicker picker) { if ((ThemeUtils.getInstance().themeType == ThemeType.TYPE_DARK) || (ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_DARK) || (ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_BLACK)) { picker.setTheme(R.style.BetterPickersDialogFragment); } else { picker.setTheme(R.style.BetterPickersDialogFragment_Light); } } public static void themeHmsView(HmsView hmsView) { if ((ThemeUtils.getInstance().themeType == ThemeType.TYPE_DARK) || (ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_DARK) || (ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_BLACK)) { hmsView.setTheme(R.style.BetterPickersDialogFragment); } else { hmsView.setTheme(R.style.BetterPickersDialogFragment_Light); } } /** * Uses reflection to find the FastScroll drawable and themes it * * @param listView the {@link android.widget.AbsListView} to theme */ public static void setFastscrollDrawable(Context context, AbsListView listView) { try { Object object; java.lang.reflect.Field field; if (ShuttleUtils.hasAndroidLPreview()) { field = AbsListView.class.getDeclaredField("mFastScroll"); } else { field = AbsListView.class.getDeclaredField("mFastScroller"); } field.setAccessible(true); object = field.get(listView); //Theme the fastscroll thumb if (ShuttleUtils.hasKitKat()) { Field thumbField = field.getType().getDeclaredField("mThumbImage"); thumbField.setAccessible(true); ImageView imageView = (ImageView) thumbField.get(object); Drawable drawable = DrawableUtils.getColoredFastScrollDrawable(context, false); imageView.setImageDrawable(drawable); thumbField.set(object, imageView); } else { Field thumbField = field.getType().getDeclaredField("mThumbDrawable"); thumbField.setAccessible(true); Drawable drawable = DrawableUtils.getColoredFastScrollDrawable(context, false); thumbField.set(object, drawable); } //Theme the SectionIndexer overlay ('Preview Image') if (ShuttleUtils.hasLollipop()) { Field previewImageField = field.getType().getDeclaredField("mPreviewImage"); previewImageField.setAccessible(true); View view = (View) previewImageField.get(object); Drawable drawable = CompatUtils.getDrawableCompat(context, R.drawable.fastscroll_label_right_material); drawable.setColorFilter(new LightingColorFilter((ColorUtils.getAccentColor()), 0)); view.setBackground(drawable); previewImageField.set(object, view); } } catch (Exception ignored) { } } public static void themeSeekBar(Context context, SizableSeekBar seekBar) { themeSeekBar(context, seekBar, false); } public static void themeSeekBar(Context context, SizableSeekBar seekBar, boolean noBackground) { int accentColor = ColorUtils.getAccentColor(); if (noBackground) { if (accentColor == ColorUtils.getPrimaryColor()) { accentColor = android.graphics.Color.WHITE; } } seekBar.setThumb(DrawableUtils.getColoredDrawable(seekBar.getThumb(), accentColor)); LayerDrawable progressDrawable = (LayerDrawable) seekBar.getProgressDrawable(); progressDrawable.setDrawableByLayerId( android.R.id.progress, DrawableUtils.getColoredDrawable(progressDrawable.findDrawableByLayerId(android.R.id.progress), accentColor)); if (!noBackground) { int color; int themeType = getThemeType(context); if (themeType == ThemeType.TYPE_DARK || themeType == ThemeType.TYPE_SOLID_DARK || themeType == ThemeType.TYPE_BLACK || themeType == ThemeType.TYPE_SOLID_BLACK) { color = android.graphics.Color.parseColor("#5a5a5a"); } else { color = android.graphics.Color.parseColor("#bfbfbf"); } progressDrawable.setDrawableByLayerId(android.R.id.background, DrawableUtils.getColoredDrawable(progressDrawable.findDrawableByLayerId(android.R.id.background), color)); } else { progressDrawable.setDrawableByLayerId(android.R.id.background, new ColorDrawable(context.getResources().getColor(android.R.color.transparent))); } } /** * Get the current base color (light or dark) depending on the theme * * @param context Context * @return The current base color (light or dark) depending on the theme */ public static int getBaseColor(Context context) { if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_LIGHT || ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_LIGHT) { return context.getResources().getColor(R.color.black); } else if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_DARK || ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_DARK || ThemeUtils.getInstance().themeType == ThemeType.TYPE_BLACK || ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_BLACK) { return context.getResources().getColor(R.color.white); } return context.getResources().getColor(R.color.white); } public static void themeTabLayout(Activity activity, SlidingTabLayout slidingTabLayout) { if (activity == null) { return; } if (activity instanceof MainActivity) { if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_DARK || ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_LIGHT || ThemeUtils.getInstance().themeType == ThemeType.TYPE_SOLID_BLACK) { slidingTabLayout.setBackgroundColor(ColorUtils.getPrimaryColor()); slidingTabLayout.setIndicatorColor(ColorUtils.getAccentColor() == ColorUtils.getPrimaryColor() ? activity.getResources().getColor(R.color.white) : ColorUtils.getAccentColor()); slidingTabLayout.setTextColor(activity.getResources().getColor(R.color.white)); } else if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_DARK || ThemeUtils.getInstance().themeType == ThemeType.TYPE_BLACK) { slidingTabLayout.setIndicatorColor(ColorUtils.getAccentColor() == ColorUtils.getPrimaryColor() ? activity.getResources().getColor(R.color.white) : ColorUtils.getAccentColor()); slidingTabLayout.setTextColor(activity.getResources().getColor(R.color.white)); } else if (ThemeUtils.getInstance().themeType == ThemeType.TYPE_LIGHT) { slidingTabLayout.setIndicatorColor(ColorUtils.getAccentColor() == ColorUtils.getPrimaryColor() ? activity.getResources().getColor(R.color.white) : ColorUtils.getAccentColor()); slidingTabLayout.setTextColor(activity.getResources().getColor(R.color.black)); } } else { slidingTabLayout.setBackgroundColor(ColorUtils.getPrimaryColor()); slidingTabLayout.setIndicatorColor(ColorUtils.getAccentColor() == ColorUtils.getPrimaryColor() ? activity.getResources().getColor(R.color.tab_underline_white) : ColorUtils.getAccentColor()); slidingTabLayout.setTextColor(activity.getResources().getColor(R.color.white)); } } public static void themeEditText(EditText editText) { int accentColor = ColorUtils.getAccentColor(); //Not sure if this check is necessary.. if (editText instanceof AppCompatEditText) { //Theme the background ((AppCompatEditText) editText).setSupportBackgroundTintList(ColorUtils.createEditTextColorStateList(editText.getContext())); } //Theme the cursor & handles setEditTextDrawablesColor(editText, accentColor); //If the parent is a TextInputLayout, theme that too if (editText.getParent() != null && editText.getParent() instanceof TextInputLayout) { setInputTextLayoutColor((TextInputLayout) editText.getParent(), accentColor); } } public static void setEditTextDrawablesColor(EditText editText, int color) { try { Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes"); fCursorDrawableRes.setAccessible(true); int mCursorDrawableRes = fCursorDrawableRes.getInt(editText); Field fEditor = TextView.class.getDeclaredField("mEditor"); fEditor.setAccessible(true); Object editor = fEditor.get(editText); Class<?> clazz = editor.getClass(); Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable"); fCursorDrawable.setAccessible(true); Drawable[] drawables = new Drawable[2]; drawables[0] = DrawableCompat.wrap(CompatUtils.getDrawableCompat(editText.getContext(), mCursorDrawableRes)); drawables[1] = DrawableCompat.wrap(CompatUtils.getDrawableCompat(editText.getContext(), mCursorDrawableRes)); DrawableCompat.setTint(drawables[0], color); DrawableCompat.setTint(drawables[1], color); fCursorDrawable.set(editor, drawables); Field fSelectHandleLeftDrawableRes = TextView.class.getDeclaredField("mTextSelectHandleLeftRes"); fSelectHandleLeftDrawableRes.setAccessible(true); int mTextSelectHandleLeftRes = fSelectHandleLeftDrawableRes.getInt(editText); Field fSelectHandleRightDrawableRes = TextView.class.getDeclaredField("mTextSelectHandleRightRes"); fSelectHandleRightDrawableRes.setAccessible(true); int mTextSelectHandleRightRes = fSelectHandleRightDrawableRes.getInt(editText); Field fSelectHandleCenterDrawableRes = TextView.class.getDeclaredField("mTextSelectHandleRes"); fSelectHandleCenterDrawableRes.setAccessible(true); int mTextSelectHandleRes = fSelectHandleCenterDrawableRes.getInt(editText); Drawable mTextSelectHandleLeftDrawable = DrawableCompat.wrap(CompatUtils.getDrawableCompat(editText.getContext(), mTextSelectHandleLeftRes)); Drawable mTextSelectHandleRightDrawable = DrawableCompat.wrap(CompatUtils.getDrawableCompat(editText.getContext(), mTextSelectHandleRightRes)); Drawable mTextSelectHandleDrawable = DrawableCompat.wrap(CompatUtils.getDrawableCompat(editText.getContext(), mTextSelectHandleRes)); if (mTextSelectHandleLeftDrawable != null) { DrawableCompat.setTint(mTextSelectHandleLeftDrawable, color); } if (mTextSelectHandleRightDrawable != null) { DrawableCompat.setTint(mTextSelectHandleRightDrawable, color); } if (mTextSelectHandleDrawable != null) { DrawableCompat.setTint(mTextSelectHandleDrawable, color); } final Field fSelectHandleLeft = editor.getClass().getDeclaredField("mSelectHandleLeft"); final Field fSelectHandleRight = editor.getClass().getDeclaredField("mSelectHandleRight"); final Field fSelectHandleCenter = editor.getClass().getDeclaredField("mSelectHandleCenter"); fSelectHandleLeft.setAccessible(true); fSelectHandleRight.setAccessible(true); fSelectHandleCenter.setAccessible(true); fSelectHandleLeft.set(editor, mTextSelectHandleLeftDrawable); fSelectHandleRight.set(editor, mTextSelectHandleRightDrawable); fSelectHandleCenter.set(editor, mTextSelectHandleDrawable); } catch (final Exception e) { e.printStackTrace(); } } public static void setInputTextLayoutColor(TextInputLayout textInputLayout, @ColorInt int color) { try { Field fDefaultTextColor = TextInputLayout.class.getDeclaredField("mDefaultTextColor"); fDefaultTextColor.setAccessible(true); fDefaultTextColor.set(textInputLayout, new ColorStateList(new int[][]{{0}}, new int[]{color})); Field fFocusedTextColor = TextInputLayout.class.getDeclaredField("mFocusedTextColor"); fFocusedTextColor.setAccessible(true); fFocusedTextColor.set(textInputLayout, new ColorStateList(new int[][]{{0}}, new int[]{color})); } catch (Exception e) { e.printStackTrace(); } } @SuppressLint("InlinedApi") public static void themeSearchView(Context context, SearchView searchView) { FilterableStateListDrawable stateListDrawable = new FilterableStateListDrawable(); NinePatchDrawable disabledDrawable = (NinePatchDrawable) CompatUtils.getDrawableCompat(context, R.drawable.abc_textfield_search_default_mtrl_alpha); NinePatchDrawable otherDrawable = (NinePatchDrawable) CompatUtils.getDrawableCompat(context, R.drawable.abc_textfield_search_activated_mtrl_alpha); int accentColor = ColorUtils.getAccentColor(); ColorFilter colorFilter = new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP); stateListDrawable.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_activated}, otherDrawable, colorFilter); stateListDrawable.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, otherDrawable, colorFilter); stateListDrawable.addState(StateSet.WILD_CARD, disabledDrawable); View searchPlate = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate); searchPlate.setBackground(stateListDrawable); EditText searchTextView = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text); try { Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes"); mCursorDrawableRes.setAccessible(true); mCursorDrawableRes.set(searchTextView, 0); } catch (final Exception | NoClassDefFoundError ignored) { } } public static void themeListView(AbsListView listView) { int accentColor = ColorUtils.getAccentColor(); try { final Class<?> clazz = AbsListView.class; final Field fEdgeGlowTop = clazz.getDeclaredField("mEdgeGlowTop"); final Field fEdgeGlowBottom = clazz.getDeclaredField("mEdgeGlowBottom"); fEdgeGlowTop.setAccessible(true); fEdgeGlowBottom.setAccessible(true); setEdgeEffectColor((EdgeEffect) fEdgeGlowTop.get(listView), accentColor); setEdgeEffectColor((EdgeEffect) fEdgeGlowBottom.get(listView), accentColor); } catch (final Exception | NoClassDefFoundError ignored) { } } public static void themeRecyclerView(RecyclerView recyclerView) { int accentColor = ColorUtils.getAccentColor(); try { final Class<?> clazz = RecyclerView.class; for (final String name : new String[]{"ensureTopGlow", "ensureBottomGlow", "ensureLeftGlow", "ensureRightGlow"}) { Method method = clazz.getDeclaredMethod(name); method.setAccessible(true); method.invoke(recyclerView); } for (final String name : new String[]{"mTopGlow", "mBottomGlow", "mRightGlow", "mLeftGlow"}) { final Field field = clazz.getDeclaredField(name); field.setAccessible(true); final Object edge = field.get(recyclerView); final Field fEdgeEffect = edge.getClass().getDeclaredField("mEdgeEffect"); fEdgeEffect.setAccessible(true); setEdgeEffectColor((EdgeEffect) fEdgeEffect.get(edge), accentColor); } } catch (final Exception | NoClassDefFoundError ignored) { } } public static void themeViewPager(ViewPager viewPager) { int accentColor = ColorUtils.getAccentColor(); try { final Class<?> clazz = ViewPager.class; final Field fEdgeGlowLeft = clazz.getDeclaredField("mLeftEdge"); final Field fEdgeGlowRight = clazz.getDeclaredField("mRightEdge"); fEdgeGlowLeft.setAccessible(true); fEdgeGlowRight.setAccessible(true); final Object edgeLeft = fEdgeGlowLeft.get(viewPager); final Field fEdgeEffectLeft = edgeLeft.getClass().getDeclaredField("mEdgeEffect"); fEdgeEffectLeft.setAccessible(true); final Object edgeRight = fEdgeGlowRight.get(viewPager); final Field fEdgeEffectRight = edgeRight.getClass().getDeclaredField("mEdgeEffect"); fEdgeEffectRight.setAccessible(true); setEdgeEffectColor((EdgeEffect) fEdgeEffectLeft.get(edgeLeft), accentColor); setEdgeEffectColor((EdgeEffect) fEdgeEffectRight.get(edgeRight), accentColor); } catch (final Exception | NoClassDefFoundError ignored) { } } public static void themeScrollView(final ScrollView scrollView) { int accentColor = ColorUtils.getAccentColor(); try { final Class<?> clazz = ScrollView.class; final Field fEdgeGlowTop = clazz.getDeclaredField("mEdgeGlowTop"); final Field fEdgeGlowBottom = clazz.getDeclaredField("mEdgeGlowBottom"); fEdgeGlowTop.setAccessible(true); fEdgeGlowBottom.setAccessible(true); setEdgeEffectColor((EdgeEffect) fEdgeGlowTop.get(scrollView), accentColor); setEdgeEffectColor((EdgeEffect) fEdgeGlowBottom.get(scrollView), accentColor); } catch (final Exception | NoClassDefFoundError ignored) { } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) static void setEdgeEffectColor(EdgeEffect edgeEffect, int color) { try { if (ShuttleUtils.hasLollipop()) { edgeEffect.setColor(color); return; } for (String name : new String[]{"mEdge", "mGlow"}) { final Field field = EdgeEffect.class.getDeclaredField(name); field.setAccessible(true); final Drawable drawable = (Drawable) field.get(edgeEffect); drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); drawable.setCallback(null); } } catch (final Exception | NoClassDefFoundError ignored) { } } public static void themeContextualActionBar(Activity activity) { if (activity != null) { View v = activity.findViewById(R.id.action_mode_bar); if (v != null) { Drawable bottom = CompatUtils.getDrawableCompat(activity, R.drawable.abc_cab_background_top_mtrl_alpha); if (bottom != null) { bottom.setColorFilter(ColorUtils.getAccentColor(), PorterDuff.Mode.SRC_ATOP); } Drawable background = new ColorDrawable(ColorUtils.getPrimaryColorDark(activity)); LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{background, bottom}); v.setBackgroundDrawable(layerDrawable); } } } /** * Traverses the hierarchy of this view (if it's a ViewGroup). If the view itself or any of its children * implement {@link Themable}, calls {@link Themable#updateTheme()} */ public static void updateThemableViews(View view) { if (view instanceof ViewGroup) { for (int i = 0, count = ((ViewGroup) view).getChildCount(); i < count; i++) { View child = ((ViewGroup) view).getChildAt(i); updateThemableViews(child); } } else { if (view instanceof Themable) { ((Themable) view).updateTheme(); } } } }