diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java index 09d7e542..07be46dd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java @@ -2,157 +2,212 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Activity; import android.app.Dialog; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.StateListDrawable; -import android.graphics.drawable.shapes.OvalShape; -import android.os.Build; import android.os.Bundle; +import android.support.annotation.ColorInt; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.support.annotation.StringRes; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.res.ResourcesCompat; -import android.support.v7.app.AppCompatActivity; -import android.view.LayoutInflater; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; +import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.util.ColorUtil; -import com.kabouzeid.gramophone.views.ColorView; +import com.kabouzeid.gramophone.views.SelectableColorView; /** - * @author Aidan Follestad (afollestad) + * @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid) */ public class ColorChooserDialog extends LeakDetectDialogFragment implements View.OnClickListener { - private ColorCallback mCallback; - private int[] mColors; - private GridView mGrid; + private Colors colors; public ColorChooserDialog() { } - private static int translucentColor(int color) { - final float factor = 0.7f; - int alpha = Math.round(Color.alpha(color) * factor); - int red = Color.red(color); - int green = Color.green(color); - int blue = Color.blue(color); - return Color.argb(alpha, red, green, blue); - } - - @NonNull - private static Drawable createSelector(int color) { - ShapeDrawable darkerCircle = new ShapeDrawable(new OvalShape()); - darkerCircle.getPaint().setColor(translucentColor(ColorUtil.shiftColorDown(color))); - StateListDrawable stateListDrawable = new StateListDrawable(); - stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, darkerCircle); - return stateListDrawable; - } + private int mCircleSize; + private ColorCallback mCallback; + private GridView mGrid; @Override public void onAttach(Activity activity) { super.onAttach(activity); + if (!(activity instanceof ColorCallback)) + throw new IllegalStateException("ColorChooserDialog needs to be shown from an Activity implementing ColorCallback."); mCallback = (ColorCallback) activity; } + private boolean isInSub() { + return getArguments().getBoolean("in_sub", false); + } + + private void setInSub(boolean value) { + getArguments().putBoolean("in_sub", value); + if (value) { + ((MaterialDialog) getDialog()).setActionButton(DialogAction.NEUTRAL, R.string.back); + } else { + ((MaterialDialog) getDialog()).setActionButton(DialogAction.NEUTRAL, null); + } + } + + private int getTopIndex() { + return getArguments().getInt("top_index", -1); + } + + private void setTopIndex(int value) { + if (getTopIndex() != value) + setSubIndex(colors.headerColorIndexes[value]); + getArguments().putInt("top_index", value); + } + + private int getSubIndex() { + return getArguments().getInt("sub_index", -1); + } + + private void setSubIndex(int value) { + getArguments().putInt("sub_index", value); + } + + private int getPreselectColor() { + return getArguments().getInt("color_preselect", -1); + } + @Override - public void onClick(@NonNull View v) { + public void onClick(View v) { if (v.getTag() != null) { final int index = (Integer) v.getTag(); - getArguments().putInt("preselect", mColors[index]); + if (isInSub()) { + setSubIndex(index); + } else { + setTopIndex(index); + setInSub(true); + } invalidateGrid(); } } + public interface ColorCallback { + void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int selectedColor); + } + + private void setColors() { + colors = Colors.fromBundle(getArguments()); + } + + private void setIndexesFor(@ColorInt int color) { + if (getTopIndex() != -1) return; + if (color != -1) { + for (int i = 0; i < colors.colors.length; i++) { + for (int z = 0; z < colors.colors[i].length; z++) { + if (color == colors.colors[i][z]) { + setTopIndex(i); + setSubIndex(z); + return; + } + } + } + } + } + + public int getTitleRes() { + return getArguments().getInt("title", 0); + } + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + setColors(); + setIndexesFor(getPreselectColor()); + + final DisplayMetrics dm = getResources().getDisplayMetrics(); + mCircleSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 56, dm); + mGrid = new GridView(getContext()); + mGrid.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + mGrid.setColumnWidth(mCircleSize); + mGrid.setNumColumns(GridView.AUTO_FIT); + + final int eightDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, dm); + mGrid.setVerticalSpacing(eightDp); + mGrid.setHorizontalSpacing(eightDp); + + final int sixteenDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, dm); + mGrid.setPadding(sixteenDp, sixteenDp, sixteenDp, sixteenDp); + mGrid.setClipToPadding(false); + mGrid.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); + mGrid.setGravity(Gravity.CENTER); + MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) - .title(getArguments().getInt("title", 0)) + .title(getTitleRes()) .autoDismiss(false) - .customView(R.layout.dialog_color_chooser, false) - .neutralText(R.string.default_str) + .customView(mGrid, false) .positiveText(R.string.select) .callback(new MaterialDialog.ButtonCallback() { @Override public void onPositive(MaterialDialog dialog) { super.onPositive(dialog); - final int title = getArguments().getInt("title", 0); - final int preselect = getArguments().getInt("preselect", -1); - mCallback.onColorSelection(title, preselect); + mCallback.onColorSelection(ColorChooserDialog.this, getSelectedColor()); dismiss(); } @Override public void onNeutral(MaterialDialog dialog) { super.onNeutral(dialog); - if (getArguments().getInt("title", 0) == R.string.primary_color) { - getArguments().putInt("preselect", ContextCompat.getColor(getContext(), R.color.indigo_500)); - } else if (getArguments().getInt("title", 0) == R.string.accent_color) { - getArguments().putInt("preselect", ContextCompat.getColor(getContext(), R.color.pink_A200)); - } + setInSub(false); invalidateGrid(); } - }) - .build(); - - final boolean primary = getArguments().getInt("title", 0) == R.string.primary_color; - final TypedArray ta = getActivity().getResources().obtainTypedArray( - primary ? R.array.colors_primary : R.array.colors_accent); - mColors = new int[ta.length()]; - for (int i = 0; i < ta.length(); i++) - mColors[i] = ta.getColor(i, 0); - ta.recycle(); - mGrid = (GridView) dialog.getCustomView(); - if (mGrid != null) { - mGrid.setNumColumns(primary ? 7 : 4); - invalidateGrid(); + }).build(); + invalidateGrid(); + if (isInSub()) { + dialog.setActionButton(DialogAction.NEUTRAL, R.string.back); } return dialog; } + @ColorInt + private int getSelectedColor() { + int selectedColor = 0; + int topIndex = getTopIndex(); + int subIndex = getSubIndex(); + if (topIndex != -1 && subIndex != -1) { + selectedColor = colors.colors[topIndex][subIndex]; + } + return selectedColor; + } + private void invalidateGrid() { if (mGrid.getAdapter() == null) { mGrid.setAdapter(new ColorGridAdapter()); - mGrid.setSelector(ResourcesCompat.getDrawable(getResources(), R.drawable.md_transparent, null)); - } else ((BaseAdapter) mGrid.getAdapter()).notifyDataSetChanged(); + } else { + ((BaseAdapter) mGrid.getAdapter()).notifyDataSetChanged(); + } } - public void show(@NonNull AppCompatActivity activity, @StringRes int title, int preselect) { - Bundle args = new Bundle(); - args.putInt("preselect", preselect); - args.putInt("title", title); - setArguments(args); - show(activity.getSupportFragmentManager(), "COLOR_SELECTOR"); - } - - public interface ColorCallback { - void onColorSelection(int title, int color); - } - - private class ColorGridAdapter extends BaseAdapter implements View.OnClickListener { + private class ColorGridAdapter extends BaseAdapter { public ColorGridAdapter() { } @Override public int getCount() { - return mColors.length; + if (isInSub()) { + return colors.colors[getTopIndex()].length; + } else { + return colors.colors.length; + } } @Override public Object getItem(int position) { - return mColors[position]; + if (isInSub()) { + return colors.colors[getTopIndex()][position]; + } else { + return colors.colors[position][colors.headerColorIndexes[position]]; + } } @Override @@ -160,39 +215,65 @@ public class ColorChooserDialog extends LeakDetectDialogFragment implements View return position; } - @Nullable @Override - public View getView(int position, @Nullable View convertView, ViewGroup parent) { - if (convertView == null) - convertView = LayoutInflater.from(getActivity()).inflate(R.layout.griditem_color_chooser, parent, false); - - final ColorView colorView = (ColorView) convertView; - colorView.setActivated(getArguments().getInt("preselect") == mColors[position]); - colorView.setBackgroundColor(mColors[position]); - colorView.setTag(position); - colorView.setOnClickListener(this); - - Drawable selector = createSelector(mColors[position]); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - int[][] states = new int[][]{ - new int[]{android.R.attr.state_pressed} - }; - int[] colors = new int[]{ - ColorUtil.shiftColorDown(mColors[position]) - }; - ColorStateList rippleColors = new ColorStateList(states, colors); - colorView.setForeground(new RippleDrawable(rippleColors, selector, null)); - } else { - colorView.setForeground(selector); + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = new SelectableColorView(getContext()); + convertView.setLayoutParams(new GridView.LayoutParams(mCircleSize, mCircleSize)); } + SelectableColorView child = (SelectableColorView) convertView; + if (isInSub()) { + child.setBackgroundColor(colors.colors[getTopIndex()][position]); + child.setSelected(getSubIndex() == position); + } else { + child.setBackgroundColor(colors.colors[position][colors.headerColorIndexes[position]]); + child.setSelected(getTopIndex() == position); + } + child.setTag(position); + child.setOnClickListener(ColorChooserDialog.this); return convertView; } + } - @Override - public void onClick(@NonNull View v) { - final int index = (Integer) v.getTag(); - getArguments().putInt("preselect", mColors[index]); - invalidateGrid(); + public static ColorChooserDialog create(@StringRes int title, @NonNull Colors colors, @ColorInt int preselectColor) { + ColorChooserDialog dialog = new ColorChooserDialog(); + Bundle args = new Bundle(); + args.putInt("title", title); + args.putInt("color_preselect", preselectColor); + + Colors.toBundle(colors, args); + + dialog.setArguments(args); + return dialog; + } + + public static final class Colors { + final int[] headerColorIndexes; + final int[][] colors; + + public Colors(int[] headerColorIndexes, int[][] colors) { + if (headerColorIndexes.length != colors.length) { + throw new IllegalArgumentException("int[] headerColorIndexes and int[][] colors must have the same length"); + } + this.headerColorIndexes = headerColorIndexes; + this.colors = colors; + } + + static void toBundle(Colors colors, Bundle bundle) { + bundle.putIntArray("top_colors", colors.headerColorIndexes); + for (int i = 0; i < colors.colors.length; i++) { + bundle.putIntArray("sub_colors_" + i, colors.colors[i]); + } + } + + static Colors fromBundle(Bundle bundle) { + int[] headerColorIndexes = bundle.getIntArray("top_colors"); + if (headerColorIndexes == null) return new Colors(new int[]{}, new int[][]{}); + int[][] colors = new int[headerColorIndexes.length][]; + for (int i = 0; i < colors.length; i++) { + colors[i] = bundle.getIntArray("sub_colors_" + i); + } + return new Colors(headerColorIndexes, colors); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/MaterialColorHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/MaterialColorHelper.java new file mode 100644 index 00000000..371fb4a0 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/MaterialColorHelper.java @@ -0,0 +1,388 @@ +package com.kabouzeid.gramophone.helper; + +import android.graphics.Color; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class MaterialColorHelper { + public static int[] createPrimaryColorIndexes() { + return new int[]{ + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5 + }; + } + + public static int[][] createPrimaryColors() { + return new int[][]{ + new int[]{ + Color.parseColor("#FFEBEE"), + Color.parseColor("#FFCDD2"), + Color.parseColor("#EF9A9A"), + Color.parseColor("#E57373"), + Color.parseColor("#EF5350"), + Color.parseColor("#F44336"), + Color.parseColor("#E53935"), + Color.parseColor("#D32F2F"), + Color.parseColor("#C62828"), + Color.parseColor("#B71C1C") + }, + new int[]{ + Color.parseColor("#FCE4EC"), + Color.parseColor("#F8BBD0"), + Color.parseColor("#F48FB1"), + Color.parseColor("#F06292"), + Color.parseColor("#EC407A"), + Color.parseColor("#E91E63"), + Color.parseColor("#D81B60"), + Color.parseColor("#C2185B"), + Color.parseColor("#AD1457"), + Color.parseColor("#880E4F") + }, + new int[]{ + Color.parseColor("#F3E5F5"), + Color.parseColor("#E1BEE7"), + Color.parseColor("#CE93D8"), + Color.parseColor("#BA68C8"), + Color.parseColor("#AB47BC"), + Color.parseColor("#9C27B0"), + Color.parseColor("#8E24AA"), + Color.parseColor("#7B1FA2"), + Color.parseColor("#6A1B9A"), + Color.parseColor("#4A148C") + }, + new int[]{ + Color.parseColor("#EDE7F6"), + Color.parseColor("#D1C4E9"), + Color.parseColor("#B39DDB"), + Color.parseColor("#9575CD"), + Color.parseColor("#7E57C2"), + Color.parseColor("#673AB7"), + Color.parseColor("#5E35B1"), + Color.parseColor("#512DA8"), + Color.parseColor("#4527A0"), + Color.parseColor("#311B92") + }, + new int[]{ + Color.parseColor("#E8EAF6"), + Color.parseColor("#C5CAE9"), + Color.parseColor("#9FA8DA"), + Color.parseColor("#7986CB"), + Color.parseColor("#5C6BC0"), + Color.parseColor("#3F51B5"), + Color.parseColor("#3949AB"), + Color.parseColor("#303F9F"), + Color.parseColor("#283593"), + Color.parseColor("#1A237E") + }, + new int[]{ + Color.parseColor("#E3F2FD"), + Color.parseColor("#BBDEFB"), + Color.parseColor("#90CAF9"), + Color.parseColor("#64B5F6"), + Color.parseColor("#42A5F5"), + Color.parseColor("#2196F3"), + Color.parseColor("#1E88E5"), + Color.parseColor("#1976D2"), + Color.parseColor("#1565C0"), + Color.parseColor("#0D47A1") + }, + new int[]{ + Color.parseColor("#E1F5FE"), + Color.parseColor("#B3E5FC"), + Color.parseColor("#81D4FA"), + Color.parseColor("#4FC3F7"), + Color.parseColor("#29B6F6"), + Color.parseColor("#03A9F4"), + Color.parseColor("#039BE5"), + Color.parseColor("#0288D1"), + Color.parseColor("#0277BD"), + Color.parseColor("#01579B") + }, + new int[]{ + Color.parseColor("#E0F7FA"), + Color.parseColor("#B2EBF2"), + Color.parseColor("#80DEEA"), + Color.parseColor("#4DD0E1"), + Color.parseColor("#26C6DA"), + Color.parseColor("#00BCD4"), + Color.parseColor("#00ACC1"), + Color.parseColor("#0097A7"), + Color.parseColor("#00838F"), + Color.parseColor("#006064") + }, + new int[]{ + Color.parseColor("#E0F2F1"), + Color.parseColor("#B2DFDB"), + Color.parseColor("#80CBC4"), + Color.parseColor("#4DB6AC"), + Color.parseColor("#26A69A"), + Color.parseColor("#009688"), + Color.parseColor("#00897B"), + Color.parseColor("#00796B"), + Color.parseColor("#00695C"), + Color.parseColor("#004D40") + }, + new int[]{ + Color.parseColor("#E8F5E9"), + Color.parseColor("#C8E6C9"), + Color.parseColor("#A5D6A7"), + Color.parseColor("#81C784"), + Color.parseColor("#66BB6A"), + Color.parseColor("#4CAF50"), + Color.parseColor("#43A047"), + Color.parseColor("#388E3C"), + Color.parseColor("#2E7D32"), + Color.parseColor("#1B5E20") + }, + new int[]{ + Color.parseColor("#F1F8E9"), + Color.parseColor("#DCEDC8"), + Color.parseColor("#C5E1A5"), + Color.parseColor("#AED581"), + Color.parseColor("#9CCC65"), + Color.parseColor("#8BC34A"), + Color.parseColor("#7CB342"), + Color.parseColor("#689F38"), + Color.parseColor("#558B2F"), + Color.parseColor("#33691E") + }, + new int[]{ + Color.parseColor("#F9FBE7"), + Color.parseColor("#F0F4C3"), + Color.parseColor("#E6EE9C"), + Color.parseColor("#DCE775"), + Color.parseColor("#D4E157"), + Color.parseColor("#CDDC39"), + Color.parseColor("#C0CA33"), + Color.parseColor("#AFB42B"), + Color.parseColor("#9E9D24"), + Color.parseColor("#827717") + }, + new int[]{ + Color.parseColor("#FFFDE7"), + Color.parseColor("#FFF9C4"), + Color.parseColor("#FFF59D"), + Color.parseColor("#FFF176"), + Color.parseColor("#FFEE58"), + Color.parseColor("#FFEB3B"), + Color.parseColor("#FDD835"), + Color.parseColor("#FBC02D"), + Color.parseColor("#F9A825"), + Color.parseColor("#F57F17") + }, + new int[]{ + Color.parseColor("#FFF8E1"), + Color.parseColor("#FFECB3"), + Color.parseColor("#FFE082"), + Color.parseColor("#FFD54F"), + Color.parseColor("#FFCA28"), + Color.parseColor("#FFC107"), + Color.parseColor("#FFB300"), + Color.parseColor("#FFA000"), + Color.parseColor("#FF8F00"), + Color.parseColor("#FF6F00") + }, + new int[]{ + Color.parseColor("#FFF3E0"), + Color.parseColor("#FFE0B2"), + Color.parseColor("#FFCC80"), + Color.parseColor("#FFB74D"), + Color.parseColor("#FFA726"), + Color.parseColor("#FF9800"), + Color.parseColor("#FB8C00"), + Color.parseColor("#F57C00"), + Color.parseColor("#EF6C00"), + Color.parseColor("#E65100") + }, + new int[]{ + Color.parseColor("#FBE9E7"), + Color.parseColor("#FFCCBC"), + Color.parseColor("#FFAB91"), + Color.parseColor("#FF8A65"), + Color.parseColor("#FF7043"), + Color.parseColor("#FF5722"), + Color.parseColor("#F4511E"), + Color.parseColor("#E64A19"), + Color.parseColor("#D84315"), + Color.parseColor("#BF360C") + }, + new int[]{ + Color.parseColor("#EFEBE9"), + Color.parseColor("#D7CCC8"), + Color.parseColor("#BCAAA4"), + Color.parseColor("#A1887F"), + Color.parseColor("#8D6E63"), + Color.parseColor("#795548"), + Color.parseColor("#6D4C41"), + Color.parseColor("#5D4037"), + Color.parseColor("#4E342E"), + Color.parseColor("#3E2723") + }, + new int[]{ + Color.parseColor("#FAFAFA"), + Color.parseColor("#F5F5F5"), + Color.parseColor("#EEEEEE"), + Color.parseColor("#E0E0E0"), + Color.parseColor("#BDBDBD"), + Color.parseColor("#9E9E9E"), + Color.parseColor("#757575"), + Color.parseColor("#616161"), + Color.parseColor("#424242"), + Color.parseColor("#212121"), + }, + new int[]{ + Color.parseColor("#ECEFF1"), + Color.parseColor("#CFD8DC"), + Color.parseColor("#B0BEC5"), + Color.parseColor("#90A4AE"), + Color.parseColor("#78909C"), + Color.parseColor("#607D8B"), + Color.parseColor("#546E7A"), + Color.parseColor("#455A64"), + Color.parseColor("#37474F"), + Color.parseColor("#263238") + } + }; + } + + public static int[] createAccentColorIndexes() { + return new int[]{ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + }; + } + + public static int[][] createAccentColors() { + return new int[][]{ + new int[]{ + Color.parseColor("#ff8a80"), + Color.parseColor("#ff5252"), + Color.parseColor("#ff1744"), + Color.parseColor("#d50000") + }, + + new int[]{ + Color.parseColor("#ff80ab"), + Color.parseColor("#ff4081"), + Color.parseColor("#f50057"), + Color.parseColor("#c51162") + }, + new int[]{ + Color.parseColor("#ea80fc"), + Color.parseColor("#e040fb"), + Color.parseColor("#d500f9"), + Color.parseColor("#aa00ff") + }, + new int[]{ + Color.parseColor("#b388ff"), + Color.parseColor("#7c4dff"), + Color.parseColor("#651fff"), + Color.parseColor("#6200ea") + }, + new int[]{ + Color.parseColor("#8c9eff"), + Color.parseColor("#536dfe"), + Color.parseColor("#3d5afe"), + Color.parseColor("#304ffe") + }, + new int[]{ + Color.parseColor("#82b1ff"), + Color.parseColor("#448aff"), + Color.parseColor("#2979ff"), + Color.parseColor("#2962ff") + }, + new int[]{ + Color.parseColor("#80d8ff"), + Color.parseColor("#40c4ff"), + Color.parseColor("#00b0ff"), + Color.parseColor("#0091ea") + }, + new int[]{ + Color.parseColor("#84ffff"), + Color.parseColor("#18ffff"), + Color.parseColor("#00e5ff"), + Color.parseColor("#00b8d4") + }, + new int[]{ + Color.parseColor("#a7ffeb"), + Color.parseColor("#64ffda"), + Color.parseColor("#1de9b6"), + Color.parseColor("#00bfa5") + }, + new int[]{ + Color.parseColor("#b9f6ca"), + Color.parseColor("#69f0ae"), + Color.parseColor("#00e676"), + Color.parseColor("#00c853") + }, + new int[]{ + Color.parseColor("#ccff90"), + Color.parseColor("#b2ff59"), + Color.parseColor("#76ff03"), + Color.parseColor("#64dd17") + }, + new int[]{ + Color.parseColor("#f4ff81"), + Color.parseColor("#eeff41"), + Color.parseColor("#c6ff00"), + Color.parseColor("#aeea00") + }, + new int[]{ + Color.parseColor("#ffff8d"), + Color.parseColor("#ffff00"), + Color.parseColor("#ffea00"), + Color.parseColor("#ffd600") + }, + new int[]{ + Color.parseColor("#ffe57f"), + Color.parseColor("#ffd740"), + Color.parseColor("#ffc400"), + Color.parseColor("#ffab00") + }, + new int[]{ + Color.parseColor("#ffd180"), + Color.parseColor("#ffab40"), + Color.parseColor("#ff9100"), + Color.parseColor("#ff6d00") + }, + new int[]{ + Color.parseColor("#ff9e80"), + Color.parseColor("#ff6e40"), + Color.parseColor("#ff3d00"), + Color.parseColor("#dd2c00") + }, + }; + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/prefs/DynamicPreferenceCategory.java b/app/src/main/java/com/kabouzeid/gramophone/prefs/DynamicPreferenceCategory.java index 21553c80..dc0c8a02 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/prefs/DynamicPreferenceCategory.java +++ b/app/src/main/java/com/kabouzeid/gramophone/prefs/DynamicPreferenceCategory.java @@ -25,7 +25,7 @@ public class DynamicPreferenceCategory extends PreferenceCategory { this(context, null, 0); } - public DynamicPreferenceCategory(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) { + public DynamicPreferenceCategory(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setLayoutResource(R.layout.preference_category_custom); setSelectable(false); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index 3eeee80b..68db6834 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -10,6 +10,7 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; +import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.Toolbar; @@ -18,6 +19,7 @@ import android.view.View; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.dialogs.ColorChooserDialog; +import com.kabouzeid.gramophone.helper.MaterialColorHelper; import com.kabouzeid.gramophone.prefs.ColorChooserPreference; import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity; import com.kabouzeid.gramophone.util.NavigationUtil; @@ -48,11 +50,14 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia } @Override - public void onColorSelection(int title, int color) { - if (title == R.string.primary_color) { - PreferenceUtil.getInstance(this).setThemeColorPrimary(color); - } else if (title == R.string.accent_color) { - PreferenceUtil.getInstance(this).setThemeColorAccent(color); + public void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int selectedColor) { + switch (dialog.getTitleRes()) { + case R.string.primary_color: + PreferenceUtil.getInstance(this).setThemeColorPrimary(selectedColor); + break; + case R.string.accent_color: + PreferenceUtil.getInstance(this).setThemeColorAccent(selectedColor); + break; } recreateIfThemeChanged(); } @@ -133,10 +138,12 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia primaryColor.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(@NonNull Preference preference) { - new ColorChooserDialog().show( - ((SettingsActivity) getActivity()), - preference.getTitleRes(), - ((SettingsActivity) getActivity()).getThemeColorPrimary()); + ColorChooserDialog + .create(preference.getTitleRes(), + new ColorChooserDialog.Colors(MaterialColorHelper.createPrimaryColorIndexes(), MaterialColorHelper.createPrimaryColors()), + PreferenceUtil.getInstance(getActivity()).getThemeColorPrimary(getActivity()) + ) + .show(((SettingsActivity) getActivity()).getSupportFragmentManager(), "COLOR_CHOOSER"); return true; } }); @@ -146,10 +153,12 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia accentColor.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(@NonNull Preference preference) { - new ColorChooserDialog().show( - ((SettingsActivity) getActivity()), - preference.getTitleRes(), - ((SettingsActivity) getActivity()).getThemeColorAccent()); + ColorChooserDialog + .create(preference.getTitleRes(), + new ColorChooserDialog.Colors(MaterialColorHelper.createAccentColorIndexes(), MaterialColorHelper.createAccentColors()), + PreferenceUtil.getInstance(getActivity()).getThemeColorAccent(getActivity()) + ) + .show(((SettingsActivity) getActivity()).getSupportFragmentManager(), "COLOR_CHOOSER"); return true; } }); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index bb21630f..68491b10 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -80,7 +80,7 @@ import butterknife.ButterKnife; /** * @author Karim Abou Zeid (kabouzeid) - *

+ *

* Do not use {@link #setContentView(int)} but wrap your layout with * {@link #wrapSlidingMusicPanelAndFab(int)} first and then return it in {@link #createContentView()} */ @@ -669,24 +669,14 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi setSeekBarTint(progressSlider, thumbColor, progressColor); } - // note that this is not exactly the same as in ColorUtil - @SuppressWarnings("ResourceType") + @ColorInt private static int shiftColorUp(@ColorInt int color) { - int alpha = Color.alpha(color); - float[] hsv = new float[3]; - Color.colorToHSV(color, hsv); - hsv[2] *= 1.2f; // value component - return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); + return ColorUtil.shiftColor(color, 1.2f); } - // note that this is not exactly the same as in ColorUtil - @SuppressWarnings("ResourceType") + @ColorInt private static int shiftColorDown(@ColorInt int color) { - int alpha = Color.alpha(color); - float[] hsv = new float[3]; - Color.colorToHSV(color, hsv); - hsv[2] *= 0.8f; // value component - return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); + return ColorUtil.shiftColor(color, 0.8f); } private static void setSeekBarTint(SeekBar seekBar, @ColorInt int thumbColor, @ColorInt int progressColor) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java index 61feaf5c..93b932e3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java @@ -6,6 +6,7 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.support.annotation.AttrRes; import android.support.annotation.ColorInt; +import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; @@ -19,6 +20,7 @@ import com.kabouzeid.gramophone.R; public class ColorUtil { public static final int PALETTE_BITMAP_SIZE = 100; + @ColorInt public static int generateColor(Context context, Bitmap bitmap) { return getColor(context, generatePalette(bitmap)); } @@ -29,6 +31,7 @@ public class ColorUtil { .generate(); } + @ColorInt public static int getColor(Context context, @Nullable Palette palette) { if (palette != null) { if (palette.getVibrantSwatch() != null) { @@ -48,6 +51,7 @@ public class ColorUtil { return ColorUtil.resolveColor(context, R.attr.default_bar_color); } + @ColorInt public static int resolveColor(@NonNull Context context, @AttrRes int colorAttr) { TypedArray a = context.obtainStyledAttributes(new int[]{colorAttr}); int resId = a.getColor(0, 0); @@ -55,38 +59,46 @@ public class ColorUtil { return resId; } + @ColorInt public static int getOpaqueColor(@ColorInt int color) { return color | 0xFF000000; } + @ColorInt public static int getColorWithAlpha(float alpha, @ColorInt int baseColor) { int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24; int rgb = 0x00ffffff & baseColor; return a + rgb; } + @ColorInt + public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) { + if (by == 1f) return color; + int alpha = Color.alpha(color); + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[2] *= by; // value component + return getColorWithAlpha(alpha, Color.HSVToColor(hsv)); + } + @SuppressWarnings("ResourceType") + @ColorInt public static int shiftColorDown(@ColorInt int color) { - int alpha = Color.alpha(color); - float[] hsv = new float[3]; - Color.colorToHSV(color, hsv); - hsv[2] *= 0.9f; // value component - return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); + return shiftColor(color, 0.9f); } @SuppressWarnings("ResourceType") + @ColorInt public static int shiftColorUp(@ColorInt int color) { - int alpha = Color.alpha(color); - float[] hsv = new float[3]; - Color.colorToHSV(color, hsv); - hsv[2] *= 1.1f; // value component - return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); + return shiftColor(color, 1.1f); } + @ColorInt public static int getPrimaryTextColor(final Context context, boolean dark) { return dark ? ContextCompat.getColor(context, R.color.primary_text_default_material_light) : ContextCompat.getColor(context, R.color.primary_text_default_material_dark); } + @ColorInt public static int getSecondaryTextColor(final Context context, boolean dark) { return dark ? ContextCompat.getColor(context, R.color.secondary_text_default_material_light) : ContextCompat.getColor(context, R.color.secondary_text_default_material_dark); } @@ -103,14 +115,17 @@ public class ColorUtil { return getLuminance(backgroundColor) > (255f / 1.3f); } + @ColorInt public static int getPrimaryTextColorForBackground(final Context context, @ColorInt int backgroundColor) { return getPrimaryTextColor(context, useDarkTextColorOnBackground(backgroundColor)); } + @ColorInt public static int getSecondaryTextColorForBackground(final Context context, @ColorInt int backgroundColor) { return getSecondaryTextColor(context, useDarkTextColorOnBackground(backgroundColor)); } + @ColorInt public static int getFabDrawableColorForBackground(final Context context, @ColorInt int backgroundColor) { return getPrimaryTextColor(context, useDarkFabDrawableOnBackground(backgroundColor)); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/Util.java b/app/src/main/java/com/kabouzeid/gramophone/util/Util.java index 905bcaae..abbd99b3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/Util.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/Util.java @@ -9,6 +9,7 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; +import android.support.annotation.AttrRes; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -80,6 +81,13 @@ public class Util { return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; } + public static Drawable resolveDrawable(@NonNull Context context, @AttrRes int drawableAttr) { + TypedArray a = context.obtainStyledAttributes(new int[]{drawableAttr}); + Drawable drawable = a.getDrawable(0); + a.recycle(); + return drawable; + } + public static Drawable getTintedDrawable(@NonNull Context context, @DrawableRes int drawableResId, int color) { Drawable drawable = ContextCompat.getDrawable(context, drawableResId); if (drawable != null) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/ColorView.java b/app/src/main/java/com/kabouzeid/gramophone/views/ColorView.java index e4f25878..a79ee585 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/ColorView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/ColorView.java @@ -1,13 +1,8 @@ package com.kabouzeid.gramophone.views; import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.widget.FrameLayout; @@ -17,11 +12,9 @@ import com.kabouzeid.gramophone.util.ColorUtil; public class ColorView extends FrameLayout { - private final Bitmap mCheck; private final Paint paint; private final Paint paintBorder; private final int borderWidth; - private Paint paintCheck; public ColorView(@NonNull Context context) { this(context, null, 0); @@ -33,10 +26,7 @@ public class ColorView extends FrameLayout { public ColorView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - final int checkSize = (int) context.getResources().getDimension(R.dimen.circle_view_check); - mCheck = getResizedBitmap(BitmapFactory.decodeResource(context.getResources(), - R.drawable.ic_checkbox_marked_circle_outline_white_24dp), checkSize, checkSize); - borderWidth = (int) getResources().getDimension(R.dimen.circle_view_border); + borderWidth = getResources().getDimensionPixelSize(R.dimen.color_view_border); paint = new Paint(); paint.setAntiAlias(true); @@ -44,31 +34,13 @@ public class ColorView extends FrameLayout { paintBorder = new Paint(); paintBorder.setAntiAlias(true); - paintCheck = new Paint(); - paintCheck.setAntiAlias(true); - setWillNotDraw(false); } - private static Bitmap getResizedBitmap(@NonNull Bitmap bm, int newHeight, int newWidth) { - int width = bm.getWidth(); - int height = bm.getHeight(); - float scaleWidth = ((float) newWidth) / width; - float scaleHeight = ((float) newHeight) / height; - Matrix matrix = new Matrix(); - matrix.postScale(scaleWidth, scaleHeight); - Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); - if (bm != resizedBitmap) { - bm.recycle(); - } - return resizedBitmap; - } - @Override public void setBackgroundColor(int color) { paint.setColor(color); paintBorder.setColor(ColorUtil.shiftColorDown(color)); - paintCheck.setColorFilter(new PorterDuffColorFilter(ColorUtil.getFabDrawableColorForBackground(getContext(), color), PorterDuff.Mode.SRC_IN)); requestLayout(); invalidate(); } @@ -102,10 +74,5 @@ public class ColorView extends FrameLayout { int circleCenter = (canvasSize - (borderWidth * 2)) / 2; canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder); canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint); - - if (isActivated()) { - final int offset = (canvasSize / 2) - (mCheck.getWidth() / 2); - canvas.drawBitmap(mCheck, offset, offset, paintCheck); - } } } \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/SelectableColorView.java b/app/src/main/java/com/kabouzeid/gramophone/views/SelectableColorView.java new file mode 100644 index 00000000..ea868c70 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/views/SelectableColorView.java @@ -0,0 +1,184 @@ +package com.kabouzeid.gramophone.views; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.StateListDrawable; +import android.graphics.drawable.shapes.OvalShape; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.FrameLayout; + +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.util.ColorUtil; + + +public class SelectableColorView extends FrameLayout { + + private final int borderWidthSmall; + private final int borderWidthLarge; + + private Paint outerPaint; + private Paint gapPaint; + private Paint innerPaint; + private boolean mSelected; + + public SelectableColorView(Context context) { + this(context, null, 0); + } + + public SelectableColorView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SelectableColorView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + final Resources r = getResources(); + borderWidthSmall = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, r.getDisplayMetrics()); + borderWidthLarge = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, r.getDisplayMetrics()); + + gapPaint = new Paint(); + gapPaint.setAntiAlias(true); + gapPaint.setColor(ColorUtil.resolveColor(context, R.attr.cardBackgroundColor)); + + innerPaint = new Paint(); + innerPaint.setAntiAlias(true); + + outerPaint = new Paint(); + outerPaint.setAntiAlias(true); + + setWillNotDraw(false); + } + + private void update(@ColorInt int color) { + innerPaint.setColor(color); + outerPaint.setColor(ColorUtil.shiftColorDown(color)); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + int[][] states = new int[][]{ + new int[]{android.R.attr.state_pressed} + }; + int[] colors = new int[]{createSelectedColor(color)}; + ColorStateList rippleColors = new ColorStateList(states, colors); + Drawable mask = new ShapeDrawable(new OvalShape()); + RippleDrawable rippleDrawable = new RippleDrawable(rippleColors, null, mask); + + setForeground(rippleDrawable); + } else { + ShapeDrawable pressedDrawable = new ShapeDrawable(new OvalShape()); + pressedDrawable.getPaint().setColor(createSelectedColor(color)); + StateListDrawable stateListDrawable = new StateListDrawable(); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable); + + setForeground(stateListDrawable); + } + } + + @ColorInt + private static int createSelectedColor(int color) { + if (ColorUtil.useDarkTextColorOnBackground(color)) { + return ColorUtil.shiftColor(color, 0.8f); + } else { + return ColorUtil.shiftColor(color, 1.2f); + } + } + + @Override + public void setBackgroundColor(@ColorInt int color) { + update(color); + requestLayout(); + invalidate(); + } + + @Override + public void setBackgroundResource(@ColorRes int color) { + setBackgroundColor(ContextCompat.getColor(getContext(), color)); + } + + /** + * @deprecated + */ + @Deprecated + @Override + public void setBackground(Drawable background) { + throw new IllegalStateException("Cannot use setBackground() on CircleView."); + } + + /** + * @deprecated + */ + @SuppressWarnings("deprecation") + @Deprecated + @Override + public void setBackgroundDrawable(Drawable background) { + throw new IllegalStateException("Cannot use setBackgroundDrawable() on CircleView."); + } + + /** + * @deprecated + */ + @SuppressWarnings("deprecation") + @Deprecated + @Override + public void setActivated(boolean activated) { + throw new IllegalStateException("Cannot use setActivated() on CircleView."); + } + + public void setSelected(boolean selected) { + mSelected = selected; + requestLayout(); + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) { + int width = MeasureSpec.getSize(widthMeasureSpec); + //noinspection SuspiciousNameCombination + int height = width; + if (heightMode == MeasureSpec.AT_MOST) + height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec)); + setMeasuredDimension(width, height); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + final int outerRadius = getMeasuredWidth() / 2; + if (mSelected) { + final int whiteRadius = outerRadius - borderWidthLarge; + final int innerRadius = whiteRadius - borderWidthSmall; + canvas.drawCircle(getMeasuredWidth() / 2, + getMeasuredHeight() / 2, + outerRadius, + outerPaint); + canvas.drawCircle(getMeasuredWidth() / 2, + getMeasuredHeight() / 2, + whiteRadius, + gapPaint); + canvas.drawCircle(getMeasuredWidth() / 2, + getMeasuredHeight() / 2, + innerRadius, + innerPaint); + } else { + canvas.drawCircle(getMeasuredWidth() / 2, + getMeasuredHeight() / 2, + outerRadius, + innerPaint); + } + } +} diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml deleted file mode 100644 index 093fc062..00000000 --- a/app/src/main/res/values/arrays.xml +++ /dev/null @@ -1,261 +0,0 @@ - - - - - #e57373 - #ef5350 - #f44336 - #e53935 - #d32f2f - #c62828 - #b71c1c - - - #f06292 - #ec407a - #e91e63 - #d81b60 - #c2185b - #ad1457 - #880e4f - - #ba68c8 - #ab47bc - #9c27b0 - #8e24aa - #7b1fa2 - #6a1b9a - #4a148c - - - #9575cd - #7e57c2 - #673ab7 - #5e35b1 - #512da8 - #4527a0 - #311b92 - - - #7986cb - #5c6bc0 - #3f51b5 - #3949ab - #303f9f - #283593 - #1a237e - - - #64b5f6 - #42a5f5 - #2196f3 - #1e88e5 - #1976d2 - #1565c0 - #0d47a1 - - - #4fc3f7 - #29b6f6 - #03a9f4 - #039be5 - #0288d1 - #0277bd - #01579b - - - #4dd0e1 - #26c6da - #00bcd4 - #00acc1 - #0097a7 - #00838f - #006064 - - - #4db6ac - #26a69a - #009688 - #00897b - #00796b - #00695c - #004d40 - - - #81c784 - #66bb6a - #4caf50 - #43a047 - #388e3c - #2e7d32 - #1b5e20 - - - #aed581 - #9ccc65 - #8bc34a - #7cb342 - #689f38 - #558b2f - #33691e - - - #dce775 - #d4e157 - #cddc39 - #c0ca33 - #afb42b - #9e9d24 - #827717 - - - #fff176 - #ffee58 - #ffeb3b - #fdd835 - #fbc02d - #f9a825 - #f57f17 - - - #ffd54f - #ffca28 - #ffc107 - #ffb300 - #ffa000 - #ff8f00 - #ff6f00 - - - #ffb74d - #ffa726 - #ff9800 - #fb8c00 - #f57c00 - #ef6c00 - #e65100 - - - #ff8a65 - #ff7043 - #ff5722 - #f4511e - #e64a19 - #d84315 - #bf360c - - - #a1887f - #8d6e63 - #795548 - #6d4c41 - #5d4037 - #4e342e - #3e2723 - - #e0e0e0 - #bdbdbd - #9e9e9e - #757575 - #616161 - #424242 - #212121 - - #90a4ae - #78909c - #607d8b - #546e7a - #455a64 - #37474f - #263238 - - - - - - #ff8a80 - #ff5252 - #ff1744 - #d50000 - - #ff80ab - #ff4081 - #f50057 - #c51162 - - #ea80fc - #e040fb - #d500f9 - #aa00ff - - #b388ff - #7c4dff - #651fff - #6200ea - - #8c9eff - #536dfe - #3d5afe - #304ffe - - #82b1ff - #448aff - #2979ff - #2962ff - - #80d8ff - #40c4ff - #00b0ff - #0091ea - - #84ffff - #18ffff - #00e5ff - #00b8d4 - - #a7ffeb - #64ffda - #1de9b6 - #00bfa5 - - #b9f6ca - #69f0ae - #00e676 - #00c853 - - #ccff90 - #b2ff59 - #76ff03 - #64dd17 - - #f4ff81 - #eeff41 - #c6ff00 - #aeea00 - - #ffff8d - #ffff00 - #ffea00 - #ffd600 - - #ffe57f - #ffd740 - #ffc400 - #ffab00 - - #ffd180 - #ffab40 - #ff9100 - #ff6d00 - - #ff9e80 - #ff6e40 - #ff3d00 - #dd2c00 - - #fff - #000 - - - - \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index c069970f..bf3e781c 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -33,9 +33,8 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 56dp 36dp - - 1dp - 24dp + 1dp + 20sp -17dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2bec95b..318da8b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -174,4 +174,5 @@ Special thanks to Changelog Permission to access external storage denied. + back