Cherish: Add ColorSelectPreference

pulled from Omnilib repo from omnirom for history/authors check
https://github.com/omnirom/android_packages_apps_OmniLib/commits/android-10

Change-Id: I5999c551ce0273f5c3b25ff45179a10a9969bbe8
This commit is contained in:
Josh Fox (XlxFoXxlX)
2020-02-21 22:22:18 -05:00
committed by Hưng Phan
parent 0d3f02daee
commit e02805e3aa
12 changed files with 1848 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2010 Daniel Nilsson
Copyright (C) 2012 THe CyanogenMod Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/alert_dialog_padding_material"
android:paddingStart="@dimen/alert_dialog_padding_material"
android:paddingEnd="@dimen/alert_dialog_padding_material" >
<com.cherish.settings.ui.ColorPickerView
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp" />
<LinearLayout
android:id="@+id/color_panel_view"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="4dp"
android:orientation="horizontal" >
<EditText
android:id="@+id/hex_color_input"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:digits="0123456789ABCDEFabcdef"
android:inputType="textNoSuggestions"
android:maxLength="6" />
<com.cherish.settings.ui.ColorPanelView
android:id="@+id/color_panel"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:layout_weight="0.5" />
</LinearLayout>
<LinearLayout
android:id="@+id/color_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="4dp"
android:orientation="horizontal" >
<Spinner
android:id="@+id/color_list_spinner"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0.5" />
<com.cherish.settings.ui.ColorPanelView
android:id="@+id/color_list_panel"
android:layout_width="0px"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_weight="0.5" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textViewName"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textAppearance="?android:attr/textAppearanceMedium" >
</TextView>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground"
android:clipToPadding="false" >
<LinearLayout
android:id="@+id/icon_frame"
style="@style/preference_icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:clipToPadding="false"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="48dp"
android:maxHeight="48dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="12dp"
android:paddingBottom="12dp">
<TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="1" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp">
<ImageView
android:id="@+id/light_color"
android:layout_width="@dimen/color_preference_width"
android:layout_height="@dimen/color_preference_height"
android:layout_gravity="center" />
</LinearLayout>
</LinearLayout>

View File

@@ -613,4 +613,14 @@
<item>2</item>
<item>3</item>
</string-array>
<string-array name="entries_led_colors" translatable="false">
<item>@string/led_color_green</item>
<item>@string/led_color_red</item>
</string-array>
<string-array name="values_led_colors" translatable="false">
<item>#FF00FF00</item>
<item>#FFFF0000</item>
</string-array>
</resources>

View File

@@ -28,4 +28,10 @@
<attr name="ledPreview" format="boolean" />
<attr name="alphaSlider" format="boolean" />
</declare-styleable>
<declare-styleable name="ColorSelectPreference">
<attr name="ledPreview" format="boolean" />
<attr name="multiColor" format="boolean" />
<attr name="withAlpha" format="boolean" />
</declare-styleable>
</resources>

View File

@@ -16,8 +16,12 @@
-->
<resources>
<!-- Color Picker -->
<dimen name="picker_circle_preview_size">26dp</dimen>
<dimen name="oval_notification_size">26dp</dimen>
<dimen name="alert_dialog_padding_material">20dp</dimen>
<dimen name="color_preference_width">18dip</dimen>
<dimen name="color_preference_height">18dip</dimen>
<dimen name="fod_picker_item_margin">20dp</dimen>
<dimen name="fod_picker_item_size">100dp</dimen>

View File

@@ -58,6 +58,8 @@
<string name="hex_hint">#ff000000</string>
<string name="set">Set</string>
<string name="color_default">Default</string>
<string name="led_color_green">Green</string>
<string name="led_color_red">Red</string>
<!-- Lockscreen battery info indicator -->
<string name="lockscreen_battery_info_title">Lockscreen charging info</string>
@@ -722,5 +724,9 @@
<string name="pulse_custom_div">Bar spacing</string>
<string name="pulse_filled_block_size">Block size</string>
<string name="pulse_empty_block_size">Block spacing</string>
<!-- does the device have multi color led support or only
a fixed set of led colors -->
<bool name="config_has_multi_color_led">true</bool>
</resources>

View File

@@ -0,0 +1,330 @@
/*
* Copyright (C) 2010 Daniel Nilsson
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cherish.settings.preferences;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.InputFilter;
import android.text.InputFilter.LengthFilter;
import android.util.Pair;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.cherish.settings.R;
import com.cherish.settings.ui.ColorPanelView;
import com.cherish.settings.ui.ColorPickerView;
import com.cherish.settings.ui.ColorPickerView.OnColorChangedListener;
import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.Locale;
public class ColorSelectDialog extends AlertDialog implements
ColorPickerView.OnColorChangedListener, TextWatcher, OnFocusChangeListener {
private static final String TAG = "ColorSelectDialog";
private final static String STATE_KEY_COLOR = "BatteryLightDialog:color";
private ColorPickerView mColorPicker;
private EditText mHexColorInput;
private ColorPanelView mNewColor;
private LayoutInflater mInflater;
private boolean mMultiColor = true;
private Spinner mColorList;
private LinearLayout mColorListView;
private LinearLayout mColorPanelView;
private ColorPanelView mNewListColor;
private LedColorAdapter mLedColorAdapter;
private boolean mWithAlpha;
private boolean mShowLedPreview;
private boolean mShowMultiColor;
private NotificationManager mNoMan;
private Context mContext;
protected ColorSelectDialog(Context context, int initialColor, boolean showMultiColor, boolean showLedPreview, boolean withAlpha) {
super(context);
mContext = context;
mShowLedPreview = showLedPreview;
mWithAlpha = withAlpha;
mShowMultiColor = showMultiColor;
mMultiColor =
(getContext().getResources().getBoolean(R.bool.config_has_multi_color_led) || mShowMultiColor);
init(initialColor);
}
private void init(int color) {
// To fight color banding.
getWindow().setFormat(PixelFormat.RGBA_8888);
setUp(color);
}
/**
* This function sets up the dialog with the proper values. If the speedOff parameters
* has a -1 value disable both spinners
*
* @param color - the color to set
* @param speedOn - the flash time in ms
* @param speedOff - the flash length in ms
*/
private void setUp(int color) {
mInflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = mInflater.inflate(R.layout.dialog_battery_settings, null);
mNoMan = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mColorPicker = (ColorPickerView) layout.findViewById(R.id.color_picker_view);
mHexColorInput = (EditText) layout.findViewById(R.id.hex_color_input);
mNewColor = (ColorPanelView) layout.findViewById(R.id.color_panel);
mColorPanelView = (LinearLayout) layout.findViewById(R.id.color_panel_view);
mColorListView = (LinearLayout) layout.findViewById(R.id.color_list_view);
mColorList = (Spinner) layout.findViewById(R.id.color_list_spinner);
mNewListColor = (ColorPanelView) layout.findViewById(R.id.color_list_panel);
mColorPicker.setOnColorChangedListener(this);
mHexColorInput.setOnFocusChangeListener(this);
setAlphaSliderVisible(mWithAlpha);
mColorPicker.setColor(color, true);
showLed(color);
mColorList = (Spinner) layout.findViewById(R.id.color_list_spinner);
mLedColorAdapter = new LedColorAdapter(
R.array.entries_led_colors,
R.array.values_led_colors);
mColorList.setAdapter(mLedColorAdapter);
mColorList.setSelection(mLedColorAdapter.getColorPosition(color));
mColorList.setOnItemSelectedListener(mColorListListener);
setView(layout);
// show and hide the correct UI depending if we have multi-color led or not
if (mMultiColor){
mColorListView.setVisibility(View.GONE);
mColorPicker.setVisibility(View.VISIBLE);
mColorPanelView.setVisibility(View.VISIBLE);
} else {
mColorListView.setVisibility(View.VISIBLE);
mColorPicker.setVisibility(View.GONE);
mColorPanelView.setVisibility(View.GONE);
}
}
private AdapterView.OnItemSelectedListener mColorListListener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int color = mLedColorAdapter.getColor(position);
mNewListColor.setColor(color);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
@Override
public Bundle onSaveInstanceState() {
Bundle state = super.onSaveInstanceState();
state.putInt(STATE_KEY_COLOR, getColor());
switchOffLed();
return state;
}
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
mColorPicker.setColor(state.getInt(STATE_KEY_COLOR), true);
}
@Override
public void onColorChanged(int color) {
final boolean hasAlpha = mWithAlpha;
final String format = hasAlpha ? "%08x" : "%06x";
final int mask = hasAlpha ? 0xFFFFFFFF : 0x00FFFFFF;
mNewColor.setColor(color);
mHexColorInput.setText(String.format(Locale.US, format, color & mask));
showLed(color);
}
private void showLed(int color) {
if (mShowLedPreview) {
if (color == 0xFFFFFFFF) {
// argb white doesn't work
color = 0xffffff;
}
mNoMan.forceShowLedLight(color);
}
}
public void switchOffLed() {
if (mShowLedPreview) {
mNoMan.forceShowLedLight(-1);
}
}
@Override
public void onStop() {
super.onStop();
switchOffLed();
}
public void setAlphaSliderVisible(boolean visible) {
mHexColorInput.setFilters(new InputFilter[] { new InputFilter.LengthFilter(visible ? 8 : 6) } );
mColorPicker.setAlphaSliderVisible(visible);
}
public int getColor() {
if (mMultiColor){
return mColorPicker.getColor();
} else {
return mNewListColor.getColor();
}
}
class LedColorAdapter extends BaseAdapter implements SpinnerAdapter {
private ArrayList<Pair<String, Integer>> mColors;
public LedColorAdapter(int ledColorResource, int ledValueResource) {
mColors = new ArrayList<Pair<String, Integer>>();
String[] color_names = getContext().getResources().getStringArray(ledColorResource);
String[] color_values = getContext().getResources().getStringArray(ledValueResource);
for(int i = 0; i < color_values.length; ++i) {
try {
int color = Color.parseColor(color_values[i]);
mColors.add(new Pair<String, Integer>(color_names[i], color));
} catch (IllegalArgumentException ex) {
// Number format is incorrect, ignore entry
}
}
}
/**
* Will return the position of the spinner entry with the specified
* color. Returns 0 if there is no such entry.
*/
public int getColorPosition(int color) {
for (int position = 0; position < getCount(); ++position) {
if (getItem(position).second.equals(color)) {
return position;
}
}
return 0;
}
public int getColor(int position) {
Pair<String, Integer> item = getItem(position);
if (item != null){
return item.second;
}
// -1 is white
return -1;
}
@Override
public int getCount() {
return mColors.size();
}
@Override
public Pair<String, Integer> getItem(int position) {
return mColors.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = mInflater.inflate(R.layout.led_color_item, null);
}
Pair<String, Integer> entry = getItem(position);
((TextView) view.findViewById(R.id.textViewName)).setText(entry.first);
return view;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String hexColor = mHexColorInput.getText().toString();
if (!hexColor.isEmpty()) {
try {
int color = Color.parseColor('#' + hexColor);
if (!mWithAlpha) {
color |= 0xFF000000; // set opaque
}
mColorPicker.setColor(color);
mNewColor.setColor(color);
} catch (IllegalArgumentException ex) {
// Number format is incorrect, ignore
}
}
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
mHexColorInput.removeTextChangedListener(this);
InputMethodManager inputMethodManager = (InputMethodManager) getContext()
.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
} else {
mHexColorInput.addTextChangedListener(this);
}
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cherish.settings.preferences;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
import com.cherish.settings.R;
public class ColorSelectPreference extends Preference implements DialogInterface.OnDismissListener {
private static String TAG = "ColorSelectPreference";
public static final int DEFAULT_COLOR = 0xFFFFFF; //White
private ImageView mLightColorView;
private Resources mResources;
private int mColorValue;
private Dialog mDialog;
private boolean mShowLedPreview;
private boolean mShowMultiColor;
private boolean mWithAlpha;
/**
* @param context
* @param attrs
*/
public ColorSelectPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mColorValue = DEFAULT_COLOR;
init(context, attrs);
}
public ColorSelectPreference(Context context, int color) {
super(context, null);
mColorValue = color;
init(context, null);
}
public ColorSelectPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mColorValue = DEFAULT_COLOR;
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.preference_color_select);
mResources = getContext().getResources();
if (attrs != null) {
final TypedArray attributes = context.obtainStyledAttributes(attrs,
R.styleable.ColorSelectPreference);
final TypedValue useWithAlpha = attributes.peekValue(
R.styleable.ColorSelectPreference_withAlpha);
if (useWithAlpha != null) {
mWithAlpha = (useWithAlpha.type == TypedValue.TYPE_INT_BOOLEAN
&& useWithAlpha.data != 0);
}
final TypedValue useLedPreview = attributes.peekValue(
R.styleable.ColorSelectPreference_ledPreview);
if (useLedPreview != null) {
mShowLedPreview = (useLedPreview.type == TypedValue.TYPE_INT_BOOLEAN
&& useLedPreview.data != 0);
}
final TypedValue useMultiColor = attributes.peekValue(
R.styleable.ColorSelectPreference_multiColor);
if (useMultiColor != null) {
mShowMultiColor = (useMultiColor.type == TypedValue.TYPE_INT_BOOLEAN
&& useMultiColor.data != 0);
}
}
}
public void setColor(int color) {
mColorValue = color;
updatePreferenceViews();
}
public int getColor() {
return mColorValue;
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mLightColorView = (ImageView) holder.findViewById(R.id.light_color);
updatePreferenceViews();
}
private void updatePreferenceViews() {
final int width = (int) mResources.getDimension(R.dimen.color_preference_width);
final int height = (int) mResources.getDimension(R.dimen.color_preference_height);
if (mLightColorView != null) {
mLightColorView.setEnabled(true);
mLightColorView.setImageDrawable(createRectShape(width, height, 0xFF000000 | mColorValue));
}
}
@Override
protected void onClick() {
if (mDialog != null && mDialog.isShowing()) return;
mDialog = getDialog();
mDialog.setOnDismissListener(this);
mDialog.show();
}
public Dialog getDialog() {
final ColorSelectDialog d = new ColorSelectDialog(getContext(),
0xFF000000 | mColorValue, mShowMultiColor, mShowLedPreview, mWithAlpha);
d.setButton(AlertDialog.BUTTON_POSITIVE, mResources.getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mShowLedPreview) {
mColorValue = d.getColor() & 0x00FFFFFF; // strip alpha, led does not support it
d.switchOffLed();
} else {
mColorValue = d.getColor();
}
updatePreferenceViews();
callChangeListener(new Integer(mColorValue));
}
});
d.setButton(AlertDialog.BUTTON_NEGATIVE, mResources.getString(android.R.string.cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
d.switchOffLed();
}
});
return d;
}
private static ShapeDrawable createRectShape(int width, int height, int color) {
ShapeDrawable shape = new ShapeDrawable(new RectShape());
shape.setIntrinsicHeight(height);
shape.setIntrinsicWidth(width);
shape.getPaint().setColor(color);
return shape;
}
@Override
public void onDismiss(DialogInterface dialog) {
mDialog = null;
}
public void setWithAlpha(boolean value) {
mWithAlpha = value;
}
public void setWithLedPreview(boolean value) {
mShowLedPreview = value;
}
public void setWithMultiColor(boolean value) {
mShowMultiColor = value;
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2010 Daniel Nilsson
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cherish.settings.ui;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.Drawable;
/**
* This drawable that draws a simple white and gray chess board pattern. It's
* pattern you will often see as a background behind a partly transparent image
* in many applications.
*
* @author Daniel Nilsson
*/
public class AlphaPatternDrawable extends Drawable {
private int mRectangleSize = 10;
private Paint mPaint = new Paint();
private Paint mPaintWhite = new Paint();
private Paint mPaintGray = new Paint();
private int numRectanglesHorizontal;
private int numRectanglesVertical;
/**
* Bitmap in which the pattern will be cached.
*/
private Bitmap mBitmap;
public AlphaPatternDrawable(int rectangleSize) {
mRectangleSize = rectangleSize;
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
@Override
public void draw(Canvas canvas) {
if (mBitmap != null) {
canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
}
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
}
@Override
public void setColorFilter(ColorFilter cf) {
throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
int height = bounds.height();
int width = bounds.width();
numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
generatePatternBitmap();
}
/**
* This will generate a bitmap with the pattern as big as the rectangle we
* were allow to draw on. We do this to cache the bitmap so we don't need
* to recreate it each time draw() is called since it takes a few
* milliseconds.
*/
private void generatePatternBitmap() {
if (getBounds().width() <= 0 || getBounds().height() <= 0) {
return;
}
mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmap);
Rect r = new Rect();
boolean verticalStartWhite = true;
for (int i = 0; i <= numRectanglesVertical; i++) {
boolean isWhite = verticalStartWhite;
for (int j = 0; j <= numRectanglesHorizontal; j++) {
r.top = i * mRectangleSize;
r.left = j * mRectangleSize;
r.bottom = r.top + mRectangleSize;
r.right = r.left + mRectangleSize;
canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
isWhite = !isWhite;
}
verticalStartWhite = !verticalStartWhite;
}
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2010 Daniel Nilsson
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cherish.settings.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* This class draws a panel which which will be filled with a color which can be
* set. It can be used to show the currently selected color which you will get
* from the {@link ColorPickerView}.
*
* @author Daniel Nilsson
*/
public class ColorPanelView extends View {
/**
* The width in pixels of the border surrounding the color panel.
*/
private final static float BORDER_WIDTH_PX = 1;
private static float mDensity = 1f;
private int mBorderColor = 0xff6E6E6E;
private int mColor = 0xff000000;
private Paint mBorderPaint;
private Paint mColorPaint;
private RectF mDrawingRect;
private RectF mColorRect;
private AlphaPatternDrawable mAlphaPattern;
public ColorPanelView(Context context) {
this(context, null);
}
public ColorPanelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorPanelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mBorderPaint = new Paint();
mColorPaint = new Paint();
mDensity = getContext().getResources().getDisplayMetrics().density;
}
@Override
protected void onDraw(Canvas canvas) {
final RectF rect = mColorRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(mDrawingRect, mBorderPaint);
}
if (mAlphaPattern != null) {
mAlphaPattern.draw(canvas);
}
mColorPaint.setColor(mColor);
canvas.drawRect(rect, mColorPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDrawingRect = new RectF();
mDrawingRect.left = getPaddingLeft();
mDrawingRect.right = w - getPaddingRight();
mDrawingRect.top = getPaddingTop();
mDrawingRect.bottom = h - getPaddingBottom();
setUpColorRect();
}
private void setUpColorRect() {
final RectF dRect = mDrawingRect;
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX;
float right = dRect.right - BORDER_WIDTH_PX;
mColorRect = new RectF(left, top, right, bottom);
mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
mAlphaPattern.setBounds(Math.round(mColorRect.left),
Math.round(mColorRect.top),
Math.round(mColorRect.right),
Math.round(mColorRect.bottom));
}
/**
* Set the color that should be shown by this view.
*
* @param color
*/
public void setColor(int color) {
mColor = color;
invalidate();
}
/**
* Get the color currently show by this view.
*
* @return
*/
public int getColor() {
return mColor;
}
/**
* Set the color of the border surrounding the panel.
*
* @param color
*/
public void setBorderColor(int color) {
mBorderColor = color;
invalidate();
}
/**
* Get the color of the border surrounding the panel.
*/
public int getBorderColor() {
return mBorderColor;
}
}

View File

@@ -0,0 +1,841 @@
/*
* Copyright (C) 2010 Daniel Nilsson
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cherish.settings.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff.Mode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Shader.TileMode;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Displays a color picker to the user and allow them to select a color. A
* slider for the alpha channel is also available. Enable it by setting
* setAlphaSliderVisible(boolean) to true.
*
* @author Daniel Nilsson
*/
public class ColorPickerView extends View {
public interface OnColorChangedListener {
public void onColorChanged(int color);
}
private final static int PANEL_SAT_VAL = 0;
private final static int PANEL_HUE = 1;
private final static int PANEL_ALPHA = 2;
/**
* The width in pixels of the border surrounding all color panels.
*/
private final static float BORDER_WIDTH_PX = 1;
/**
* The width in dp of the hue panel.
*/
private float HUE_PANEL_WIDTH = 30f;
/**
* The height in dp of the alpha panel
*/
private float ALPHA_PANEL_HEIGHT = 20f;
/**
* The distance in dp between the different color panels.
*/
private float PANEL_SPACING = 10f;
/**
* The radius in dp of the color palette tracker circle.
*/
private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
/**
* The dp which the tracker of the hue or alpha panel will extend outside of
* its bounds.
*/
private float RECTANGLE_TRACKER_OFFSET = 2f;
private static float mDensity = 1f;
private OnColorChangedListener mListener;
private Paint mSatValPaint;
private Paint mSatValTrackerPaint;
private Paint mHuePaint;
private Paint mHueTrackerPaint;
private Paint mAlphaPaint;
private Paint mAlphaTextPaint;
private Paint mBorderPaint;
private Shader mValShader;
private Shader mSatShader;
private Shader mHueShader;
private Shader mAlphaShader;
private int mAlpha = 0xff;
private float mHue = 360f;
private float mSat = 0f;
private float mVal = 0f;
private String mAlphaSliderText = "Alpha";
private int mSliderTrackerColor = 0xff1c1c1c;
private int mBorderColor = 0xff6E6E6E;
private boolean mShowAlphaPanel = false;
/*
* To remember which panel that has the "focus" when processing hardware
* button data.
*/
private int mLastTouchedPanel = PANEL_SAT_VAL;
/**
* Offset from the edge we must have or else the finger tracker will get
* clipped when it is drawn outside of the view.
*/
private float mDrawingOffset;
/*
* Distance form the edges of the view of where we are allowed to draw.
*/
private RectF mDrawingRect;
private RectF mSatValRect;
private RectF mHueRect;
private RectF mAlphaRect;
private AlphaPatternDrawable mAlphaPattern;
private Point mStartTouchPoint = null;
public ColorPickerView(Context context) {
this(context, null);
}
public ColorPickerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mDensity = getContext().getResources().getDisplayMetrics().density;
PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
RECTANGLE_TRACKER_OFFSET *= mDensity;
HUE_PANEL_WIDTH *= mDensity;
ALPHA_PANEL_HEIGHT *= mDensity;
PANEL_SPACING = PANEL_SPACING * mDensity;
mDrawingOffset = calculateRequiredOffset();
initPaintTools();
// Needed for receiving track ball motion events.
setFocusableInTouchMode(true);
setFocusable(true);
setClickable(true);
}
private void initPaintTools() {
mSatValPaint = new Paint();
mSatValTrackerPaint = new Paint();
mHuePaint = new Paint();
mHueTrackerPaint = new Paint();
mAlphaPaint = new Paint();
mAlphaTextPaint = new Paint();
mBorderPaint = new Paint();
mSatValTrackerPaint.setStyle(Style.STROKE);
mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
mSatValTrackerPaint.setAntiAlias(true);
mHueTrackerPaint.setColor(mSliderTrackerColor);
mHueTrackerPaint.setStyle(Style.STROKE);
mHueTrackerPaint.setStrokeWidth(2f * mDensity);
mHueTrackerPaint.setAntiAlias(true);
mAlphaTextPaint.setColor(0xff1c1c1c);
mAlphaTextPaint.setTextSize(14f * mDensity);
mAlphaTextPaint.setAntiAlias(true);
mAlphaTextPaint.setTextAlign(Align.CENTER);
mAlphaTextPaint.setFakeBoldText(true);
}
private float calculateRequiredOffset() {
float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
return offset * 1.5f;
}
private int[] buildHueColorArray() {
int[] hue = new int[361];
int count = 0;
for (int i = hue.length - 1; i >= 0; i--, count++) {
hue[count] = Color.HSVToColor(new float[] {
i, 1f, 1f
});
}
return hue;
}
@Override
protected void onDraw(Canvas canvas) {
if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) {
return;
}
drawSatValPanel(canvas);
drawHuePanel(canvas);
drawAlphaPanel(canvas);
}
private void drawSatValPanel(Canvas canvas) {
final RectF rect = mSatValRect;
int rgb = Color.HSVToColor(new float[] {
mHue, 1f, 1f
});
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX,
rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
}
// On Honeycomb+ we need to use software rendering to create the shader properly
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
// Get the overlaying gradients ready and create the ComposeShader
if (mValShader == null) {
mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
0xffffffff, 0xff000000, TileMode.CLAMP);
}
mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
0xffffffff, rgb, TileMode.CLAMP);
ComposeShader mShader = new ComposeShader(mValShader, mSatShader, Mode.MULTIPLY);
mSatValPaint.setShader(mShader);
canvas.drawRect(rect, mSatValPaint);
Point p = satValToPoint(mSat, mVal);
mSatValTrackerPaint.setColor(0xff000000);
canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity,
mSatValTrackerPaint);
mSatValTrackerPaint.setColor(0xffdddddd);
canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
}
private void drawHuePanel(Canvas canvas) {
final RectF rect = mHueRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
rect.top - BORDER_WIDTH_PX,
rect.right + BORDER_WIDTH_PX,
rect.bottom + BORDER_WIDTH_PX,
mBorderPaint);
}
if (mHueShader == null) {
mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
buildHueColorArray(), null, TileMode.CLAMP);
mHuePaint.setShader(mHueShader);
}
canvas.drawRect(rect, mHuePaint);
float rectHeight = 4 * mDensity / 2;
Point p = hueToPoint(mHue);
RectF r = new RectF();
r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
r.top = p.y - rectHeight;
r.bottom = p.y + rectHeight;
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
}
private void drawAlphaPanel(Canvas canvas) {
if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) {
return;
}
final RectF rect = mAlphaRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
rect.top - BORDER_WIDTH_PX,
rect.right + BORDER_WIDTH_PX,
rect.bottom + BORDER_WIDTH_PX,
mBorderPaint);
}
mAlphaPattern.draw(canvas);
float[] hsv = new float[] {
mHue, mSat, mVal
};
int color = Color.HSVToColor(hsv);
int acolor = Color.HSVToColor(0, hsv);
mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
color, acolor, TileMode.CLAMP);
mAlphaPaint.setShader(mAlphaShader);
canvas.drawRect(rect, mAlphaPaint);
if (mAlphaSliderText != null && mAlphaSliderText != "") {
canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity,
mAlphaTextPaint);
}
float rectWidth = 4 * mDensity / 2;
Point p = alphaToPoint(mAlpha);
RectF r = new RectF();
r.left = p.x - rectWidth;
r.right = p.x + rectWidth;
r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
}
private Point hueToPoint(float hue) {
final RectF rect = mHueRect;
final float height = rect.height();
Point p = new Point();
p.y = (int) (height - (hue * height / 360f) + rect.top);
p.x = (int) rect.left;
return p;
}
private Point satValToPoint(float sat, float val) {
final RectF rect = mSatValRect;
final float height = rect.height();
final float width = rect.width();
Point p = new Point();
p.x = (int) (sat * width + rect.left);
p.y = (int) ((1f - val) * height + rect.top);
return p;
}
private Point alphaToPoint(int alpha) {
final RectF rect = mAlphaRect;
final float width = rect.width();
Point p = new Point();
p.x = (int) (width - (alpha * width / 0xff) + rect.left);
p.y = (int) rect.top;
return p;
}
private float[] pointToSatVal(float x, float y) {
final RectF rect = mSatValRect;
float[] result = new float[2];
float width = rect.width();
float height = rect.height();
if (x < rect.left) {
x = 0f;
} else if (x > rect.right) {
x = width;
} else {
x = x - rect.left;
}
if (y < rect.top) {
y = 0f;
} else if (y > rect.bottom) {
y = height;
} else {
y = y - rect.top;
}
result[0] = 1.f / width * x;
result[1] = 1.f - (1.f / height * y);
return result;
}
private float pointToHue(float y) {
final RectF rect = mHueRect;
float height = rect.height();
if (y < rect.top) {
y = 0f;
} else if (y > rect.bottom) {
y = height;
} else {
y = y - rect.top;
}
return 360f - (y * 360f / height);
}
private int pointToAlpha(int x) {
final RectF rect = mAlphaRect;
final int width = (int) rect.width();
if (x < rect.left) {
x = 0;
} else if (x > rect.right) {
x = width;
} else {
x = x - (int) rect.left;
}
return 0xff - (x * 0xff / width);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean update = false;
if (event.getAction() == MotionEvent.ACTION_MOVE) {
switch (mLastTouchedPanel) {
case PANEL_SAT_VAL:
float sat,
val;
sat = mSat + x / 50f;
val = mVal - y / 50f;
if (sat < 0f) {
sat = 0f;
} else if (sat > 1f) {
sat = 1f;
}
if (val < 0f) {
val = 0f;
} else if (val > 1f) {
val = 1f;
}
mSat = sat;
mVal = val;
update = true;
break;
case PANEL_HUE:
float hue = mHue - y * 10f;
if (hue < 0f) {
hue = 0f;
} else if (hue > 360f) {
hue = 360f;
}
mHue = hue;
update = true;
break;
case PANEL_ALPHA:
if (!mShowAlphaPanel || mAlphaRect == null) {
update = false;
} else {
int alpha = (int) (mAlpha - x * 10);
if (alpha < 0) {
alpha = 0;
} else if (alpha > 0xff) {
alpha = 0xff;
}
mAlpha = alpha;
update = true;
}
break;
}
}
if (update) {
if (mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
mHue, mSat, mVal
}));
}
invalidate();
return true;
}
return super.onTrackballEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean update = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartTouchPoint = new Point((int) event.getX(), (int) event.getY());
update = moveTrackersIfNeeded(event);
break;
case MotionEvent.ACTION_MOVE:
update = moveTrackersIfNeeded(event);
break;
case MotionEvent.ACTION_UP:
mStartTouchPoint = null;
update = moveTrackersIfNeeded(event);
break;
}
if (update) {
requestFocus();
if (mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
mHue, mSat, mVal
}));
}
invalidate();
return true;
}
return super.onTouchEvent(event);
}
private boolean moveTrackersIfNeeded(MotionEvent event) {
if (mStartTouchPoint == null)
return false;
boolean update = false;
int startX = mStartTouchPoint.x;
int startY = mStartTouchPoint.y;
if (mHueRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_HUE;
mHue = pointToHue(event.getY());
update = true;
} else if (mSatValRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_SAT_VAL;
float[] result = pointToSatVal(event.getX(), event.getY());
mSat = result[0];
mVal = result[1];
update = true;
} else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_ALPHA;
mAlpha = pointToAlpha((int) event.getX());
update = true;
}
return update;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = 0;
int height = 0;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
widthAllowed = chooseWidth(widthMode, widthAllowed);
heightAllowed = chooseHeight(heightMode, heightAllowed);
if (!mShowAlphaPanel) {
height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
// If calculated height (based on the width) is more than the
// allowed height.
if (height > heightAllowed && heightMode != MeasureSpec.UNSPECIFIED) {
height = heightAllowed;
width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
} else {
width = widthAllowed;
}
} else {
width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
if (width > widthAllowed && widthMode != MeasureSpec.UNSPECIFIED) {
width = widthAllowed;
height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
} else {
height = heightAllowed;
}
}
setMeasuredDimension(width, height);
}
private int chooseWidth(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPrefferedWidth();
}
}
private int chooseHeight(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPrefferedHeight();
}
}
private int getPrefferedWidth() {
int width = getPrefferedHeight();
if (mShowAlphaPanel) {
width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
}
return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
}
private int getPrefferedHeight() {
int height = (int) (200 * mDensity);
if (mShowAlphaPanel) {
height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
}
return height;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDrawingRect = new RectF();
mDrawingRect.left = mDrawingOffset + getPaddingLeft();
mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
mDrawingRect.top = mDrawingOffset + getPaddingTop();
mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
setUpSatValRect();
setUpHueRect();
setUpAlphaRect();
}
private void setUpSatValRect() {
final RectF dRect = mDrawingRect;
float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
if (mShowAlphaPanel) {
panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
}
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = top + panelSide;
float right = left + panelSide;
mSatValRect = new RectF(left, top, right, bottom);
}
private void setUpHueRect() {
final RectF dRect = mDrawingRect;
float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX
- (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
float right = dRect.right - BORDER_WIDTH_PX;
mHueRect = new RectF(left, top, right, bottom);
}
private void setUpAlphaRect() {
if (!mShowAlphaPanel) {
return;
}
final RectF dRect = mDrawingRect;
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX;
float right = dRect.right - BORDER_WIDTH_PX;
mAlphaRect = new RectF(left, top, right, bottom);
mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
mAlphaPattern.setBounds(Math.round(mAlphaRect.left), Math
.round(mAlphaRect.top), Math.round(mAlphaRect.right), Math
.round(mAlphaRect.bottom));
}
/**
* Set a OnColorChangedListener to get notified when the color selected by
* the user has changed.
*
* @param listener
*/
public void setOnColorChangedListener(OnColorChangedListener listener) {
mListener = listener;
}
/**
* Set the color of the border surrounding all panels.
*
* @param color
*/
public void setBorderColor(int color) {
mBorderColor = color;
invalidate();
}
/**
* Get the color of the border surrounding all panels.
*/
public int getBorderColor() {
return mBorderColor;
}
/**
* Get the current color this view is showing.
*
* @return the current color.
*/
public int getColor() {
return Color.HSVToColor(mAlpha, new float[] {
mHue, mSat, mVal
});
}
/**
* Set the color the view should show.
*
* @param color The color that should be selected.
*/
public void setColor(int color) {
setColor(color, false);
}
/**
* Set the color this view should show.
*
* @param color The color that should be selected.
* @param callback If you want to get a callback to your
* OnColorChangedListener.
*/
public void setColor(int color, boolean callback) {
int alpha = Color.alpha(color);
int red = Color.red(color);
int blue = Color.blue(color);
int green = Color.green(color);
float[] hsv = new float[3];
Color.RGBToHSV(red, green, blue, hsv);
mAlpha = alpha;
mHue = hsv[0];
mSat = hsv[1];
mVal = hsv[2];
if (callback && mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
mHue, mSat, mVal
}));
}
invalidate();
}
/**
* Get the drawing offset of the color picker view. The drawing offset is
* the distance from the side of a panel to the side of the view minus the
* padding. Useful if you want to have your own panel below showing the
* currently selected color and want to align it perfectly.
*
* @return The offset in pixels.
*/
public float getDrawingOffset() {
return mDrawingOffset;
}
/**
* Set if the user is allowed to adjust the alpha panel. Default is false.
* If it is set to false no alpha will be set.
*
* @param visible
*/
public void setAlphaSliderVisible(boolean visible) {
if (mShowAlphaPanel != visible) {
mShowAlphaPanel = visible;
/*
* Reset all shader to force a recreation. Otherwise they will not
* look right after the size of the view has changed.
*/
mValShader = null;
mSatShader = null;
mHueShader = null;
mAlphaShader = null;
requestLayout();
}
}
public boolean isAlphaSliderVisible() {
return mShowAlphaPanel;
}
public void setSliderTrackerColor(int color) {
mSliderTrackerColor = color;
mHueTrackerPaint.setColor(mSliderTrackerColor);
invalidate();
}
public int getSliderTrackerColor() {
return mSliderTrackerColor;
}
/**
* Set the text that should be shown in the alpha slider. Set to null to
* disable text.
*
* @param res string resource id.
*/
public void setAlphaSliderText(int res) {
String text = getContext().getString(res);
setAlphaSliderText(text);
}
/**
* Set the text that should be shown in the alpha slider. Set to null to
* disable text.
*
* @param text Text that should be shown.
*/
public void setAlphaSliderText(String text) {
mAlphaSliderText = text;
invalidate();
}
/**
* Get the current value of the text that will be shown in the alpha slider.
*
* @return
*/
public String getAlphaSliderText() {
return mAlphaSliderText;
}
}