Skip to content

Instantly share code, notes, and snippets.

@jaredrummler
Last active January 19, 2016 11:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredrummler/26aa29331992ca7964ef to your computer and use it in GitHub Desktop.
Save jaredrummler/26aa29331992ca7964ef to your computer and use it in GitHub Desktop.
Tint edges on pre-lollipop
/*
* Copyright (C) 2015 Jared Rummler <jared.rummler@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jrummyapps.android.ui;
import android.app.Activity;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.EdgeEffectCompat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.EdgeEffect;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import java.lang.reflect.Field;
/**
* <p>Helper class to set the color of an {@link EdgeEffect} on pre-lollipop.</p>
*
* <p>Example usage in an {@link Activity}:</p>
*
* <pre>
* &#64;Override public void onStart() {
* super.onStart();
* if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
* EdgeTint.on(this).apply(getResources().getColor(R.color.color_primary));
* }
* }
* </pre>
*/
public class EdgeTint {
/**
* @param activity
* the activity to apply the edge effect on.
* @return A new {@link EdgeTint}. To set the color use {@link #apply(int)}.
*/
public static EdgeTint on(Activity activity) {
return new EdgeTint((ViewGroup) activity.findViewById(android.R.id.content).getRootView());
}
/**
* @param view
* the ViewGroup to apply the edge effect on.
* @return A new {@link EdgeTint}. To set the color use {@link #apply(int)}.
*/
public static EdgeTint on(ViewGroup view) {
return new EdgeTint(view);
}
/**
* Set the color of an {@link EdgeEffect}. This uses reflection on pre-L.
*
* @param edgeEffect
* the EdgeEffect to apply the color on.
* @param color
* the color value
*/
public static void setEdgeEffectColor(EdgeEffect edgeEffect, @ColorInt int color) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
edgeEffect.setColor(color);
return;
}
for (String name : new String[]{"mEdge", "mGlow"}) {
Field field = EdgeEffect.class.getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
Drawable drawable = (Drawable) field.get(edgeEffect);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
drawable.setCallback(null); // free up any references
}
} catch (Throwable ignored) {
}
}
/**
* Set the edge-effect color on a ListView or GridView.
*
* @param listView
* The view (ListView/GridView) to set the edge color
* @param color
* the color value
*/
public static void setEdgeGlowColor(AbsListView listView, @ColorInt int color) {
try {
for (String name : new String[]{"mEdgeGlowTop", "mEdgeGlowBottom"}) {
Field field = AbsListView.class.getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
setEdgeEffectColor((EdgeEffect) field.get(listView), color);
}
} catch (Throwable ignored) {
}
}
/**
* Set the edge-effect color on a {@link HorizontalScrollView}.
*
* @param hsv
* the view to set the edge color
* @param color
* the color value
*/
public static void setEdgeGlowColor(HorizontalScrollView hsv, @ColorInt int color) {
try {
for (String name : new String[]{"mEdgeGlowLeft", "mEdgeGlowRight"}) {
Field field = HorizontalScrollView.class.getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
setEdgeEffectColor((EdgeEffect) field.get(hsv), color);
}
} catch (Throwable ignored) {
}
}
/**
* Set the edge-effect color on a {@link ScrollView}.
*
* @param scrollView
* the view to set the edge color
* @param color
* the color value
*/
public static void setEdgeGlowColor(ScrollView scrollView, int color) {
try {
for (String name : new String[]{"mEdgeGlowTop", "mEdgeGlowBottom"}) {
Field field = ScrollView.class.getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
setEdgeEffectColor((EdgeEffect) field.get(scrollView), color);
}
} catch (Throwable ignored) {
}
}
/**
* Set the edge-effect color on a {@link ViewPager}.
*
* @param viewPager
* the ViewPager
* @param color
* the color value
*/
public static void setEdgeGlowColor(ViewPager viewPager, int color) {
try {
for (String name : new String[]{"mLeftEdge", "mRightEdge"}) {
Field field = viewPager.getClass().getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
EdgeEffectCompat edge = (EdgeEffectCompat) field.get(viewPager);
Field fEdgeEffect = edge.getClass().getDeclaredField("mEdgeEffect");
fEdgeEffect.setAccessible(true);
setEdgeEffectColor((EdgeEffect) fEdgeEffect.get(edge), color);
}
} catch (Throwable ignored) {
}
}
private final ViewGroup view;
private EdgeTint(ViewGroup view) {
this.view = view;
}
/**
* Sets the color on all edge effects for the ViewGroup/Activity passed to the constructor.
*
* @param color
* the color to be applied on the {@link EdgeEffect}
*/
public void apply(int color) {
setEdgeTint(view, color);
}
private void setEdgeTint(ViewGroup viewGroup, int color) {
for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof AbsListView) {
setEdgeGlowColor((AbsListView) child, color);
} else if (child instanceof HorizontalScrollView) {
setEdgeGlowColor((HorizontalScrollView) child, color);
} else if (child instanceof ScrollView) {
setEdgeGlowColor((ScrollView) child, color);
} else if (child instanceof ViewPager) {
setEdgeGlowColor((ViewPager) child, color);
} else if (child instanceof ViewGroup) {
setEdgeTint((ViewGroup) child, color);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment