在Api Demo里面有一个叫ColorPickerDialog的对话框,该对话框扩展了Dialog 的功能,使其具备颜色选择器的功能。具体可以参考Api Demo源代码,路径为:android-sdk-windows\samples\android-7\ApiDemos\src\com\example\android\apis\graphics\ColorPickerDialog.java
本功能是基于上述的颜色选择器对话框进行扩展,模仿PreferceActivity 组件的实现方式,新建一个名为ColorPickerPreference 的类使其继承自DialogPreference 并实现其内部功能菜单,如图:
在Api Demo里面的颜色选择器是不具备有黑色和白色的选择的,这里我们虽然使用api Demo 里面的颜色选择器但其内部我们稍稍改造了一下。使其支持黑色和白色的选择,如上图中间的一条颜色条,头部和尾部分别代表黑色和白色。
为了显示的友好性,如果用户选择了颜色应该应该会有一个内容窗口或者一个文本对用户的选择做出相应的预览效果,。我们这里使用了一个TextView 做为颜色的预览效果,我们知道,Preference 的summary 只支持字符串的操作,类似下面的图:
上面代码,我们通过LayoutInflater 函数引入一个外部的布局文件,然后设置其title 和summary 并初始其颜色,通过SharedPreferences 类调用保存后的颜色值,布局文件如下:
package com.terry.util;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.terry.eBook.R;
public
class
ColorPickerPreference extends DialogPreference {
private
int
mInitialColor;
private
int
mCurrentColor;
private
ColorPickerView mCPView;
private
TextView summary;
private
static
class
ColorPickerView extends View {
private
Paint mPaint;
private
Paint mCenterPaint;
private
Paint mHSVPaint;
private
final
int
[] mColors;
private
int
[] mHSVColors;
private
boolean mRedrawHSV;
private
OnColorChangedListener mListener;
ColorPickerView(Context c, OnColorChangedListener l,
int
color) {
super(c);
mListener
=
l;
mColors
=
new
int
[] {
0xFFFF0000
,
0xFFFF00FF
,
0xFF0000FF
,
0xFF00FFFF
,
0xFF00FF00
,
0xFFFFFF00
,
0xFFFF0000
};
Shader s
=
new
SweepGradient(
,
, mColors,
null
);
mPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(s);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(
55
);
mCenterPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
mCenterPaint.setColor(color);
mCenterPaint.setStrokeWidth(
5
);
mHSVColors
=
new
int
[] {
0xFF000000
, color,
0xFFFFFFFF
};
mHSVPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
mHSVPaint.setStrokeWidth(
10
);
mRedrawHSV
=
true
;
}
private
boolean mTrackingCenter;
private
boolean mHighlightCenter;
public
int
getColor() {
return
mCenterPaint.getColor();
}
@Override
protected
void
onDraw(Canvas canvas) {
float
r
=
CENTER_X
-
mPaint.getStrokeWidth()
*
0.5f
;
canvas.translate(CENTER_X, CENTER_X);
int
c
=
mCenterPaint.getColor();
if
(mRedrawHSV) {
mHSVColors[
1
]
=
c;
mHSVPaint.setShader(
new
LinearGradient(
-
100
,
,
100
,
,
mHSVColors,
null
, Shader.TileMode.CLAMP));
}
canvas.drawOval(
new
RectF(
-
r,
-
r, r, r), mPaint);
canvas.drawCircle(
,
, CENTER_RADIUS, mCenterPaint);
canvas.drawRect(
new
RectF(
-
100
,
130
,
100
,
110
), mHSVPaint);
if
(mTrackingCenter) {
mCenterPaint.setStyle(Paint.Style.STROKE);
if
(mHighlightCenter) {
mCenterPaint.setAlpha(
0xFF
);
}
else
{
mCenterPaint.setAlpha(
0x80
);
}
canvas.drawCircle(
,
, CENTER_RADIUS
+
mCenterPaint.getStrokeWidth(), mCenterPaint);
mCenterPaint.setStyle(Paint.Style.FILL);
mCenterPaint.setColor(c);
}
mRedrawHSV
=
true
;
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
setMeasuredDimension(CENTER_X
*
2
, (CENTER_Y
+
25
)
*
2
);
}
private
static
final
int
CENTER_X
=
100
;
private
static
final
int
CENTER_Y
=
100
;
private
static
final
int
CENTER_RADIUS
=
30
;
private
int
ave(
int
s,
int
d,
float
p) {
return
s
+
java.lang.Math.round(p
*
(d
-
s));
}
private
int
interpColor(
int
colors[],
float
unit) {
if
(unit
<=
) {
return
colors[
];
}
if
(unit
>=
1
) {
return
colors[colors.length
-
1
];
}
float
p
=
unit
*
(colors.length
-
1
);
int
i
=
(
int
) p;
p
-=
i;
//
now p is just the fractional part [0...1) and i is the index
int
c0
=
colors[i];
int
c1
=
colors[i
+
1
];
int
a
=
ave(Color.alpha(c0), Color.alpha(c1), p);
int
r
=
ave(Color.red(c0), Color.red(c1), p);
int
g
=
ave(Color.green(c0), Color.green(c1), p);
int
b
=
ave(Color.blue(c0), Color.blue(c1), p);
return
Color.argb(a, r, g, b);
}
private
static
final
float
PI
=
3.1415926f
;
@Override
public
boolean onTouchEvent(MotionEvent
event
) {
float
x
=
event
.getX()
-
CENTER_X;
float
y
=
event
.getY()
-
CENTER_Y;
boolean inCenter
=
java.lang.Math.sqrt(x
*
x
+
y
*
y)
<=
CENTER_RADIUS;
switch
(
event
.getAction()) {
case
MotionEvent.ACTION_DOWN:
mTrackingCenter
=
inCenter;
if
(inCenter) {
mHighlightCenter
=
true
;
invalidate();
break
;
}
case
MotionEvent.ACTION_MOVE:
if
(mTrackingCenter) {
if
(mHighlightCenter
!=
inCenter) {
mHighlightCenter
=
inCenter;
invalidate();
}
}
else
if
((x
>=
-
100
&
x
<=
100
)
&&
(y
<=
130
&&
y
>=
110
))
//
see
//
if
//
we're
//
in
//
the
//
hsv
//
slider
{
int
a, r, g, b, c0, c1;
float
p;
//
set the center paint to this color
if
(x
<
) {
c0
=
mHSVColors[
];
c1
=
mHSVColors[
1
];
p
=
(x
+
100
)
/
100
;
}
else
{
c0
=
mHSVColors[
1
];
c1
=
mHSVColors[
2
];
p
=
x
/
100
;
}
a
=
ave(Color.alpha(c0), Color.alpha(c1), p);
r
=
ave(Color.red(c0), Color.red(c1), p);
g
=
ave(Color.green(c0), Color.green(c1), p);
b
=
ave(Color.blue(c0), Color.blue(c1), p);
mCenterPaint.setColor(Color.argb(a, r, g, b));
mRedrawHSV
=
false
;
invalidate();
}
else
{
float
angle
=
(
float
) java.lang.Math.atan2(y, x);
//
need to turn angle [-PI ... PI] into unit [0....1]
float
unit
=
angle
/
(
2
*
PI);
if
(unit
<
) {
unit
+=
1
;
}
mCenterPaint.setColor(interpColor(mColors, unit));
invalidate();
}
break
;
case
MotionEvent.ACTION_UP:
if
(mTrackingCenter) {
if
(inCenter) {
mListener.colorChanged(mCenterPaint.getColor());
}
mTrackingCenter
=
false
;
//
so we draw w/o halo
invalidate();
}
break
;
}
return
true
;
}
}
public
interface
OnColorChangedListener {
void
colorChanged(
int
color);
}
public
ColorPickerPreference(Context contex) {
this
(contex,
null
);
}
public
ColorPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public
ColorPickerPreference(Context context, AttributeSet attrs,
int
defStyle) {
super(context, attrs, defStyle);
}
@Override
protected
void
onDialogClosed(boolean positiveResult) {
if
(positiveResult) {
mCurrentColor
=
mCPView.getColor();
summary.setTextColor(mCurrentColor);
SharedPreferences.Editor editor
=
getEditor();
editor.putInt(getKey(), mCurrentColor);
editor.commit();
callChangeListener(
new
Integer(mCurrentColor));
}
}
@Override
protected
View onCreateView(ViewGroup parent) {
//
TODO Auto-generated method stub
View view
=
LayoutInflater.from(getContext()).inflate(
R.layout.preference,
null
);
TextView title
=
(TextView) view.findViewById(R.id.title);
title.setText(getTitle());
summary
=
(TextView) view.findViewById(R.id.summary);
summary.setText(getSummary());
SharedPreferences prefs
=
getPreferenceManager().getSharedPreferences();
mInitialColor
=
prefs.getInt(getKey(), Color.LTGRAY);
summary.setTextColor(mInitialColor);
return
view;
}
@Override
protected
void
onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
OnColorChangedListener l
=
new
OnColorChangedListener() {
public
void
colorChanged(
int
color) {
mCurrentColor
=
color;
onDialogClosed(
true
);
getDialog().dismiss();
}
};
LinearLayout layout
=
new
LinearLayout(getContext());
layout.setPadding(
20
,
20
,
20
,
20
);
layout.setOrientation(LinearLayout.VERTICAL);
mCPView
=
new
ColorPickerView(getContext(), l, mInitialColor);
LinearLayout.LayoutParams params1
=
new
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params1.gravity
=
Gravity.CENTER;
mCPView.setLayoutParams(params1);
layout.addView(
this
.mCPView);
layout.setId(android.R.id.widget_frame);
builder.setView(layout);
}
}