Implemented app-theme-helper. Needs to be cleaned up.

This commit is contained in:
Karim Abou Zeid 2016-01-25 22:20:59 +01:00
commit 8b98a9be85
39 changed files with 275 additions and 1370 deletions

View file

@ -3,42 +3,19 @@ package com.kabouzeid.gramophone.util;
import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v7.view.menu.ListMenuItemView;
import android.support.v7.view.menu.MenuPopupHelper;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.PathInterpolator;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import com.afollestad.materialdialogs.internal.MDTintHelper;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.kabouzeid.gramophone.R;
import java.lang.reflect.Field;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class ViewUtil {
public final static int PHONOGRAPH_ANIM_TIME = 1000;
public static Animator createBackgroundColorTransition(final View v, final int startColor, final int endColor) {
return createColorAnimator(v, "backgroundColor", startColor, endColor);
}
@ -47,8 +24,6 @@ public class ViewUtil {
return createColorAnimator(v, "textColor", startColor, endColor);
}
public final static int PHONOGRAPH_ANIM_TIME = 1000;
private static Animator createColorAnimator(Object target, String propertyName, int startColor, int endColor) {
ObjectAnimator animator;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -65,149 +40,6 @@ public class ViewUtil {
return animator;
}
/**
* Should be called in {@link android.app.Activity#onPrepareOptionsMenu(Menu)} and {@link android.app.Activity#onOptionsItemSelected(MenuItem)}
*
* @param toolbar the toolbar to apply the tint on
*/
public static void invalidateToolbarPopupMenuTint(@Nullable final Toolbar toolbar) {
if (toolbar == null) return;
toolbar.post(new Runnable() {
@Override
public void run() {
try {
Field f1 = Toolbar.class.getDeclaredField("mMenuView");
f1.setAccessible(true);
ActionMenuView actionMenuView = (ActionMenuView) f1.get(toolbar);
Field f2 = ActionMenuView.class.getDeclaredField("mPresenter");
f2.setAccessible(true);
Object presenter = f2.get(actionMenuView); // ActionMenuPresenter is not a public class, so we use Object here
Field f3 = presenter.getClass().getDeclaredField("mOverflowPopup");
f3.setAccessible(true);
MenuPopupHelper overflowMenuPopupHelper = (MenuPopupHelper) f3.get(presenter);
ViewUtil.setTintForMenuPopupHelper(overflowMenuPopupHelper);
Field f4 = presenter.getClass().getDeclaredField("mActionButtonPopup");
f4.setAccessible(true);
MenuPopupHelper subMenuPopupHelper = (MenuPopupHelper) f4.get(presenter);
ViewUtil.setTintForMenuPopupHelper(subMenuPopupHelper);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static void setTintForMenuPopupHelper(@Nullable MenuPopupHelper menuPopupHelper) {
if (menuPopupHelper == null) return;
final ListView listView = menuPopupHelper.getPopup().getListView();
listView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
try {
Field checkboxField = ListMenuItemView.class.getDeclaredField("mCheckBox");
checkboxField.setAccessible(true);
Field radioButtonField = ListMenuItemView.class.getDeclaredField("mRadioButton");
radioButtonField.setAccessible(true);
for (int i = 0; i < listView.getChildCount(); i++) {
View v = listView.getChildAt(i);
if (!(v instanceof ListMenuItemView)) continue;
ListMenuItemView iv = (ListMenuItemView) v;
CheckBox check = (CheckBox) checkboxField.get(iv);
if (check != null) {
MDTintHelper.setTint(check, ThemeSingleton.get().positiveColor.getDefaultColor());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
check.setBackground(null);
}
}
RadioButton radioButton = (RadioButton) radioButtonField.get(iv);
if (radioButton != null) {
MDTintHelper.setTint(radioButton, ThemeSingleton.get().positiveColor.getDefaultColor());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
radioButton.setBackground(null);
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
listView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
//noinspection deprecation
listView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
/**
* Call this in {@link android.app.Activity#onCreateOptionsMenu(Menu)} and everywhere where the toolbar color is changed.
*/
public static void setToolbarContentColorForBackground(@NonNull Context context, @Nullable Toolbar toolbar, @ColorInt final int backgroundColor) {
ViewUtil.setToolbarContentDark(context, toolbar, ColorUtil.useDarkTextColorOnBackground(backgroundColor));
}
public static void setToolbarContentDark(@NonNull Context context, @Nullable Toolbar toolbar, boolean dark) {
if (toolbar == null) return;
toolbar.setTitleTextColor(ColorUtil.getPrimaryTextColor(context, dark));
toolbar.setSubtitleTextColor(ColorUtil.getSecondaryTextColor(context, dark));
setToolbarIconColor(context, toolbar, getToolbarIconColor(context, dark));
}
@ColorInt
public static int getToolbarIconColor(Context context, boolean dark) {
if (dark) {
return ColorUtil.getSecondaryTextColor(context, true);
} else {
return ColorUtil.getPrimaryTextColor(context, false);
}
}
private static void setToolbarIconColor(@NonNull final Context context, @Nullable final Toolbar toolbar, @ColorInt final int color) {
if (toolbar == null) return;
toolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
toolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
final ArrayList<View> outViews = new ArrayList<>();
final String overflowDescription = context.getString(R.string.abc_action_menu_overflow_description);
toolbar.findViewsWithText(outViews, overflowDescription, View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (!outViews.isEmpty()) {
try {
ImageView overflowButton = (ImageView) outViews.get(0);
overflowButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
} catch (ClassCastException e) {
Log.e("setToolbarIconColor", "overflow button is not an ImageView", e);
}
}
Menu menu = toolbar.getMenu();
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (item.getIcon() != null) {
item.getIcon().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}
Drawable navigationIcon = toolbar.getNavigationIcon();
if (navigationIcon != null) {
navigationIcon = navigationIcon.mutate();
navigationIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN);
toolbar.setNavigationIcon(navigationIcon);
}
}
});
}
public static boolean hitTest(View v, int x, int y) {
final int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
final int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);