New color chooser dialog
This commit is contained in:
parent
48b63b7d78
commit
d8e94c1c85
12 changed files with 826 additions and 445 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ import butterknife.ButterKnife;
|
|||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
* <p/>
|
||||
* <p>
|
||||
* 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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
<resources>
|
||||
|
||||
<array name="colors_primary">
|
||||
|
||||
<item>#e57373</item>
|
||||
<item>#ef5350</item>
|
||||
<item>#f44336</item>
|
||||
<item>#e53935</item>
|
||||
<item>#d32f2f</item>
|
||||
<item>#c62828</item>
|
||||
<item>#b71c1c</item>
|
||||
|
||||
|
||||
<item>#f06292</item>
|
||||
<item>#ec407a</item>
|
||||
<item>#e91e63</item>
|
||||
<item>#d81b60</item>
|
||||
<item>#c2185b</item>
|
||||
<item>#ad1457</item>
|
||||
<item>#880e4f</item>
|
||||
|
||||
<item>#ba68c8</item>
|
||||
<item>#ab47bc</item>
|
||||
<item>#9c27b0</item>
|
||||
<item>#8e24aa</item>
|
||||
<item>#7b1fa2</item>
|
||||
<item>#6a1b9a</item>
|
||||
<item>#4a148c</item>
|
||||
|
||||
|
||||
<item>#9575cd</item>
|
||||
<item>#7e57c2</item>
|
||||
<item>#673ab7</item>
|
||||
<item>#5e35b1</item>
|
||||
<item>#512da8</item>
|
||||
<item>#4527a0</item>
|
||||
<item>#311b92</item>
|
||||
|
||||
|
||||
<item>#7986cb</item>
|
||||
<item>#5c6bc0</item>
|
||||
<item>#3f51b5</item>
|
||||
<item>#3949ab</item>
|
||||
<item>#303f9f</item>
|
||||
<item>#283593</item>
|
||||
<item>#1a237e</item>
|
||||
|
||||
|
||||
<item>#64b5f6</item>
|
||||
<item>#42a5f5</item>
|
||||
<item>#2196f3</item>
|
||||
<item>#1e88e5</item>
|
||||
<item>#1976d2</item>
|
||||
<item>#1565c0</item>
|
||||
<item>#0d47a1</item>
|
||||
|
||||
|
||||
<item>#4fc3f7</item>
|
||||
<item>#29b6f6</item>
|
||||
<item>#03a9f4</item>
|
||||
<item>#039be5</item>
|
||||
<item>#0288d1</item>
|
||||
<item>#0277bd</item>
|
||||
<item>#01579b</item>
|
||||
|
||||
|
||||
<item>#4dd0e1</item>
|
||||
<item>#26c6da</item>
|
||||
<item>#00bcd4</item>
|
||||
<item>#00acc1</item>
|
||||
<item>#0097a7</item>
|
||||
<item>#00838f</item>
|
||||
<item>#006064</item>
|
||||
|
||||
|
||||
<item>#4db6ac</item>
|
||||
<item>#26a69a</item>
|
||||
<item>#009688</item>
|
||||
<item>#00897b</item>
|
||||
<item>#00796b</item>
|
||||
<item>#00695c</item>
|
||||
<item>#004d40</item>
|
||||
|
||||
|
||||
<item>#81c784</item>
|
||||
<item>#66bb6a</item>
|
||||
<item>#4caf50</item>
|
||||
<item>#43a047</item>
|
||||
<item>#388e3c</item>
|
||||
<item>#2e7d32</item>
|
||||
<item>#1b5e20</item>
|
||||
|
||||
|
||||
<item>#aed581</item>
|
||||
<item>#9ccc65</item>
|
||||
<item>#8bc34a</item>
|
||||
<item>#7cb342</item>
|
||||
<item>#689f38</item>
|
||||
<item>#558b2f</item>
|
||||
<item>#33691e</item>
|
||||
|
||||
|
||||
<item>#dce775</item>
|
||||
<item>#d4e157</item>
|
||||
<item>#cddc39</item>
|
||||
<item>#c0ca33</item>
|
||||
<item>#afb42b</item>
|
||||
<item>#9e9d24</item>
|
||||
<item>#827717</item>
|
||||
|
||||
|
||||
<item>#fff176</item>
|
||||
<item>#ffee58</item>
|
||||
<item>#ffeb3b</item>
|
||||
<item>#fdd835</item>
|
||||
<item>#fbc02d</item>
|
||||
<item>#f9a825</item>
|
||||
<item>#f57f17</item>
|
||||
|
||||
|
||||
<item>#ffd54f</item>
|
||||
<item>#ffca28</item>
|
||||
<item>#ffc107</item>
|
||||
<item>#ffb300</item>
|
||||
<item>#ffa000</item>
|
||||
<item>#ff8f00</item>
|
||||
<item>#ff6f00</item>
|
||||
|
||||
|
||||
<item>#ffb74d</item>
|
||||
<item>#ffa726</item>
|
||||
<item>#ff9800</item>
|
||||
<item>#fb8c00</item>
|
||||
<item>#f57c00</item>
|
||||
<item>#ef6c00</item>
|
||||
<item>#e65100</item>
|
||||
|
||||
|
||||
<item>#ff8a65</item>
|
||||
<item>#ff7043</item>
|
||||
<item>#ff5722</item>
|
||||
<item>#f4511e</item>
|
||||
<item>#e64a19</item>
|
||||
<item>#d84315</item>
|
||||
<item>#bf360c</item>
|
||||
|
||||
|
||||
<item>#a1887f</item>
|
||||
<item>#8d6e63</item>
|
||||
<item>#795548</item>
|
||||
<item>#6d4c41</item>
|
||||
<item>#5d4037</item>
|
||||
<item>#4e342e</item>
|
||||
<item>#3e2723</item>
|
||||
|
||||
<item>#e0e0e0</item>
|
||||
<item>#bdbdbd</item>
|
||||
<item>#9e9e9e</item>
|
||||
<item>#757575</item>
|
||||
<item>#616161</item>
|
||||
<item>#424242</item>
|
||||
<item>#212121</item>
|
||||
|
||||
<item>#90a4ae</item>
|
||||
<item>#78909c</item>
|
||||
<item>#607d8b</item>
|
||||
<item>#546e7a</item>
|
||||
<item>#455a64</item>
|
||||
<item>#37474f</item>
|
||||
<item>#263238</item>
|
||||
|
||||
</array>
|
||||
|
||||
<array name="colors_accent">
|
||||
|
||||
<item>#ff8a80</item>
|
||||
<item>#ff5252</item>
|
||||
<item>#ff1744</item>
|
||||
<item>#d50000</item>
|
||||
|
||||
<item>#ff80ab</item>
|
||||
<item>#ff4081</item>
|
||||
<item>#f50057</item>
|
||||
<item>#c51162</item>
|
||||
|
||||
<item>#ea80fc</item>
|
||||
<item>#e040fb</item>
|
||||
<item>#d500f9</item>
|
||||
<item>#aa00ff</item>
|
||||
|
||||
<item>#b388ff</item>
|
||||
<item>#7c4dff</item>
|
||||
<item>#651fff</item>
|
||||
<item>#6200ea</item>
|
||||
|
||||
<item>#8c9eff</item>
|
||||
<item>#536dfe</item>
|
||||
<item>#3d5afe</item>
|
||||
<item>#304ffe</item>
|
||||
|
||||
<item>#82b1ff</item>
|
||||
<item>#448aff</item>
|
||||
<item>#2979ff</item>
|
||||
<item>#2962ff</item>
|
||||
|
||||
<item>#80d8ff</item>
|
||||
<item>#40c4ff</item>
|
||||
<item>#00b0ff</item>
|
||||
<item>#0091ea</item>
|
||||
|
||||
<item>#84ffff</item>
|
||||
<item>#18ffff</item>
|
||||
<item>#00e5ff</item>
|
||||
<item>#00b8d4</item>
|
||||
|
||||
<item>#a7ffeb</item>
|
||||
<item>#64ffda</item>
|
||||
<item>#1de9b6</item>
|
||||
<item>#00bfa5</item>
|
||||
|
||||
<item>#b9f6ca</item>
|
||||
<item>#69f0ae</item>
|
||||
<item>#00e676</item>
|
||||
<item>#00c853</item>
|
||||
|
||||
<item>#ccff90</item>
|
||||
<item>#b2ff59</item>
|
||||
<item>#76ff03</item>
|
||||
<item>#64dd17</item>
|
||||
|
||||
<item>#f4ff81</item>
|
||||
<item>#eeff41</item>
|
||||
<item>#c6ff00</item>
|
||||
<item>#aeea00</item>
|
||||
|
||||
<item>#ffff8d</item>
|
||||
<item>#ffff00</item>
|
||||
<item>#ffea00</item>
|
||||
<item>#ffd600</item>
|
||||
|
||||
<item>#ffe57f</item>
|
||||
<item>#ffd740</item>
|
||||
<item>#ffc400</item>
|
||||
<item>#ffab00</item>
|
||||
|
||||
<item>#ffd180</item>
|
||||
<item>#ffab40</item>
|
||||
<item>#ff9100</item>
|
||||
<item>#ff6d00</item>
|
||||
|
||||
<item>#ff9e80</item>
|
||||
<item>#ff6e40</item>
|
||||
<item>#ff3d00</item>
|
||||
<item>#dd2c00</item>
|
||||
|
||||
<item>#fff</item>
|
||||
<item>#000</item>
|
||||
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
|
@ -33,9 +33,8 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
|
|||
<dimen name="fab_icon_bound_width">56dp</dimen>
|
||||
<dimen name="fab_icon_bound_height">36dp</dimen>
|
||||
|
||||
<!-- Color Chooser Dialog -->
|
||||
<dimen name="circle_view_border">1dp</dimen>
|
||||
<dimen name="circle_view_check">24dp</dimen>
|
||||
<dimen name="color_view_border">1dp</dimen>
|
||||
|
||||
<dimen name="empty_text_size">20sp</dimen>
|
||||
|
||||
<dimen name="seek_bar_margin_left_right">-17dp</dimen>
|
||||
|
|
|
|||
|
|
@ -174,4 +174,5 @@
|
|||
<string name="special_thanks_to">Special thanks to</string>
|
||||
<string name="changelog">Changelog</string>
|
||||
<string name="permission_to_access_external_storage_denied">Permission to access external storage denied.</string>
|
||||
<string name="back">back</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue