Replaced extra vector drawable resources with programmatic tinting

This commit is contained in:
Phillip Hsu 2016-08-22 18:21:12 -07:00
parent 322682823f
commit 2a285c0558
10 changed files with 83 additions and 50 deletions

View File

@ -21,12 +21,21 @@ import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder; import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.support.annotation.AttrRes; import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.text.format.Time; import android.text.format.Time;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
@ -191,6 +200,51 @@ public class Utils {
return value.data; return value.data;
} }
/**
* Mutates the given drawable, applies the specified tint list, and sets this tinted
* drawable on the target ImageView.
*
* @param target the ImageView that should have the tinted drawable set on
* @param drawable the drawable to tint
* @param tintList Color state list to use for tinting this drawable, or null to clear the tint
*/
public static void setTintList(ImageView target, Drawable drawable, ColorStateList tintList) {
// TODO: What is the VectorDrawable counterpart for this process?
// Use a mutable instance of the drawable, so we only affect this instance.
// This is especially useful when you need to modify properties of drawables loaded from
// resources. By default, all drawables instances loaded from the same resource share a
// common state; if you modify the state of one instance, all the other instances will
// receive the same modification.
// Wrap drawable so that it may be used for tinting across the different
// API levels, via the tinting methods in this class.
drawable = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTintList(drawable, tintList);
target.setImageDrawable(drawable);
}
/**
* Returns a tinted drawable from the given drawable resource, if {@code tintList != null}.
* Otherwise, no tint will be applied.
*/
public static Drawable getTintedDrawable(@NonNull Context context,
@DrawableRes int drawableRes,
@Nullable ColorStateList tintList) {
Drawable d = DrawableCompat.wrap(ContextCompat.getDrawable(context, drawableRes).mutate());
DrawableCompat.setTintList(d, tintList);
return d;
}
/**
* Returns a tinted drawable from the given drawable resource and color resource.
*/
public static Drawable getTintedDrawable(@NonNull Context context,
@DrawableRes int drawableRes,
@ColorInt int colorInt) {
Drawable d = DrawableCompat.wrap(ContextCompat.getDrawable(context, drawableRes).mutate());
DrawableCompat.setTint(d, colorInt);
return d;
}
/** /**
* Gets dialog type (Light/Dark) from current theme * Gets dialog type (Light/Dark) from current theme
* @param context The context to use as reference for the boolean * @param context The context to use as reference for the boolean

View File

@ -1,10 +1,12 @@
package com.philliphsu.clock2.editalarm; package com.philliphsu.clock2.editalarm;
import android.content.Context; import android.content.Context;
import android.support.v4.content.ContextCompat;
import android.view.View; import android.view.View;
import android.widget.ImageButton; import android.widget.ImageButton;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.aospdatetimepicker.Utils;
/** /**
* Created by Phillip Hsu on 8/17/2016. * Created by Phillip Hsu on 8/17/2016.
@ -52,8 +54,21 @@ public class MinutesGrid extends NumbersGrid {
@Override @Override
void setTheme(Context context, boolean themeDark) { void setTheme(Context context, boolean themeDark) {
super.setTheme(context, themeDark); super.setTheme(context, themeDark);
mMinusButton.setImageResource(themeDark? R.drawable.ic_minus_circle_dark_24dp : R.drawable.ic_minus_circle_24dp); if (themeDark) {
mPlusButton.setImageResource(themeDark? R.drawable.ic_add_circle_dark_24dp : R.drawable.ic_add_circle_24dp); // Resources default to dark-themed color (#FFFFFF)
// If vector fill color is transparent, programmatically tinting will not work.
// Since dark-themed active icon color is fully opaque, use that color as the
// base color and tint at runtime as needed.
mMinusButton.setImageResource(R.drawable.ic_minus_circle_24dp);
mPlusButton.setImageResource(R.drawable.ic_add_circle_24dp);
} else {
// Tint drawables
final int colorActiveLight = ContextCompat.getColor(context, R.color.icon_color_active_light);
mMinusButton.setImageDrawable(Utils.getTintedDrawable(
context, R.drawable.ic_minus_circle_24dp, colorActiveLight));
mPlusButton.setImageDrawable(Utils.getTintedDrawable(
context, R.drawable.ic_add_circle_24dp, colorActiveLight));
}
} }
/** /**

View File

@ -45,8 +45,6 @@ import java.util.Locale;
import butterknife.Bind; import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import static com.philliphsu.clock2.util.ConversionUtils.dpToPx;
//import com.android.datetimepicker.HapticFeedbackController; //import com.android.datetimepicker.HapticFeedbackController;
//import com.android.datetimepicker.R; //import com.android.datetimepicker.R;
//import com.android.datetimepicker.Utils; //import com.android.datetimepicker.Utils;
@ -132,8 +130,6 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog implements
private int mHalfDayToggleUnselectedColor; private int mHalfDayToggleUnselectedColor;
// ====================================== MY STUFF ============================================= // ====================================== MY STUFF =============================================
// The padding in dp for the half day icon compound drawable
public static final int HALF_DAY_ICON_PADDING = 8;
// Describes both AM/PM in the 12-hour clock and the half-days of the 24-hour clock. // Describes both AM/PM in the 12-hour clock and the half-days of the 24-hour clock.
// TODO: Use the *values* of AM and PM instead. // TODO: Use the *values* of AM and PM instead.
@ -245,7 +241,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog implements
mInitialMinute = minute; mInitialMinute = minute;
mIs24HourMode = is24HourMode; mIs24HourMode = is24HourMode;
mInKbMode = false; mInKbMode = false;
mThemeDark = false; mThemeDark = true;
} }
/** /**
@ -321,17 +317,20 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog implements
TextView tv1 = (TextView) mLeftHalfDayToggle.getChildAt(0); TextView tv1 = (TextView) mLeftHalfDayToggle.getChildAt(0);
TextView tv2 = (TextView) mRightHalfDayToggle.getChildAt(0); TextView tv2 = (TextView) mRightHalfDayToggle.getChildAt(0);
if (mIs24HourMode) { if (mIs24HourMode) {
final int iconPadding = getResources().getDimensionPixelSize(R.dimen.half_day_icon_padding);
tv1.setText("00 - 11"); tv1.setText("00 - 11");
// Intrinsic bounds meaning the drawable's own bounds? So 24dp box. // Intrinsic bounds meaning the drawable's own bounds? So 24dp box.
// We need different drawable resources for each case, not a single one that we
// just tint differently, because the orientation of each one is different.
tv1.setCompoundDrawablesWithIntrinsicBounds( tv1.setCompoundDrawablesWithIntrinsicBounds(
mThemeDark? R.drawable.ic_half_day_1_dark_24dp : R.drawable.ic_half_day_1_24dp, mThemeDark? R.drawable.ic_half_day_1_dark_24dp : R.drawable.ic_half_day_1_24dp,
0, 0, 0); 0, 0, 0);
tv1.setCompoundDrawablePadding((int) dpToPx(getActivity(), HALF_DAY_ICON_PADDING)); tv1.setCompoundDrawablePadding(iconPadding);
tv2.setText("12 - 23"); tv2.setText("12 - 23");
tv2.setCompoundDrawablesWithIntrinsicBounds( tv2.setCompoundDrawablesWithIntrinsicBounds(
mThemeDark? R.drawable.ic_half_day_2_dark_24dp : R.drawable.ic_half_day_2_24dp, mThemeDark? R.drawable.ic_half_day_2_dark_24dp : R.drawable.ic_half_day_2_24dp,
0, 0, 0); 0, 0, 0);
tv2.setCompoundDrawablePadding((int) dpToPx(getActivity(), HALF_DAY_ICON_PADDING)); tv2.setCompoundDrawablePadding(iconPadding);
} else { } else {
tv1.setText(mAmText); tv1.setText(mAmText);
tv2.setText(mPmText); tv2.setText(mPmText);

View File

@ -3,13 +3,11 @@ package com.philliphsu.clock2.editalarm;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
@ -114,29 +112,13 @@ public class NumpadTimePicker extends GridLayoutNumpad {
b.setTextColor(mColors); b.setTextColor(mColors);
} }
// Get a mutable instance of the drawable, so we only affect this instance.
// This is especially useful when you need to modify properties of drawables loaded from
// resources. By default, all drawables instances loaded from the same resource share a
// common state; if you modify the state of one instance, all the other instances will
// receive the same modification.
// TODO: What is the VectorDrawable counterpart for this process?
Drawable backspaceDrawable = mBackspace.getDrawable().mutate();
// Wrap drawable so that it may be used for tinting across the different
// API levels, via the tinting methods in this class.
backspaceDrawable = DrawableCompat.wrap(backspaceDrawable);
// Prepare the tints
ColorStateList colorBackspace = ContextCompat.getColorStateList(context, ColorStateList colorBackspace = ContextCompat.getColorStateList(context,
themeDark? R.color.icon_color_dark : R.color.icon_color); themeDark? R.color.icon_color_dark : R.color.icon_color);
DrawableCompat.setTintList(backspaceDrawable, colorBackspace); Utils.setTintList(mBackspace, mBackspace.getDrawable(), colorBackspace);
mBackspace.setImageDrawable(backspaceDrawable);
// TODO: What is the VectorDrawable counterpart for this process?
Drawable iconDrawable = mFab.getDrawable().mutate();
iconDrawable = DrawableCompat.wrap(iconDrawable);
ColorStateList colorIcon = ContextCompat.getColorStateList(context, ColorStateList colorIcon = ContextCompat.getColorStateList(context,
themeDark? R.color.icon_color_dark : R.color.fab_icon_color); themeDark? R.color.icon_color_dark : R.color.fab_icon_color);
DrawableCompat.setTintList(iconDrawable, colorIcon); Utils.setTintList(mFab, mFab.getDrawable(), colorIcon);
mFab.setImageDrawable(iconDrawable);
// this.getContext() ==> default teal accent color // this.getContext() ==> default teal accent color
// application context ==> white // application context ==> white

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#8c8c8c" android:fillColor="#FFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/> android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector> </vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#FF000000" android:fillColor="#8a000000"
android:pathData="M20,15.31L23.31,12 20,8.69V4h-4.69L12,0.69 8.69,4H4v4.69L0.69,12 4,15.31V20h4.69L12,23.31 15.31,20H20v-4.69zM12,18V6c3.31,0 6,2.69 6,6s-2.69,6 -6,6z"/> android:pathData="M20,15.31L23.31,12 20,8.69V4h-4.69L12,0.69 8.69,4H4v4.69L0.69,12 4,15.31V20h4.69L12,23.31 15.31,20H20v-4.69zM12,18V6c3.31,0 6,2.69 6,6s-2.69,6 -6,6z"/>
</vector> </vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#8c8c8c" android:fillColor="#FFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z"/> android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z"/>
</vector> </vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z"/>
</vector>

View File

@ -64,4 +64,5 @@
<!--My stuff--> <!--My stuff-->
<dimen name="fab_elevation">6dp</dimen> <dimen name="fab_elevation">6dp</dimen>
<dimen name="half_day_icon_padding">8dp</dimen>
</resources> </resources>