博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
eBook 功能模块一之颜色选择器【ColorPickerPreference】自定义Preference 对话框
阅读量:7044 次
发布时间:2019-06-28

本文共 11282 字,大约阅读时间需要 37 分钟。

在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 只支持字符串的操作,类似下面的图:

如上图,只支持类型类型为CharSequence和字符所在的资源ID位置,那么我们这里如何使其支持颜色的显示和动态更换颜色呢?

这一切都在神奇的回调函数,onCreateView 里面这个方法先于 onBindView 执行,在里面初始化视图并且返回视图。具体处理见下面代码:

 

    @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;
    }

 

 

上面代码,我们通过LayoutInflater 函数引入一个外部的布局文件,然后设置其title 和summary 并初始其颜色,通过SharedPreferences 类调用保存后的颜色值,布局文件如下:

 

<?
xml version="1.0" encoding="UTF-8"
?>
<
LinearLayout 
android:id
="@+id/LinearLayout01"
    android:layout_width
="fill_parent"
 android:layout_height
="fill_parent"
    xmlns:android
="http://schemas.android.com/apk/res/android"
>
    
<
RelativeLayout 
android:layout_width
="fill_parent"
        android:gravity
="center"
 android:layout_height
="fill_parent"
>
        
<
TextView 
android:id
="@+id/title"
 android:layout_width
="wrap_content"
            android:layout_marginLeft
="15dp"
 android:textAppearance
="?android:attr/textAppearanceLarge"
            android:layout_height
="wrap_content"
></
TextView
>
        
<
ImageView 
android:src
="@drawable/ic_dialog_menu_generic"
            android:layout_marginRight
="15dp"
 android:layout_alignParentRight
="true"
            android:layout_width
="wrap_content"
 android:layout_height
="wrap_content"
></
ImageView
>
        
<
TextView 
android:id
="@+id/summary"
 android:layout_below
="@id/title"
            android:layout_marginLeft
="15dp"
 android:layout_width
="wrap_content"
            android:layout_height
="wrap_content"
></
TextView
>
    
</
RelativeLayout
>
</
LinearLayout
>

 

 

 

实始化对话框的回调函数里面我们为其添加一个ColorPickerDialog 本身的颜色改变的事件监听并为其初始化颜色值,代码如下:

 

@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);
    }

 

 

当对话框关闭时,即选择完颜色后,我们就要马上回去更新文本的颜色和将颜色值保存到键值里面,代码如下:

 

    @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));
        }
    }

 

通过重写,onDialogClosed 回调函数,到这一步整个的封装就己结束,在XML可以通过如下使用:

 

<
com.terry.util.ColorPickerPreference
            
android:key
="colorpiker"
 android:persistent
="true"
 android:summary
="@string/app_name"
            android:dialogTitle
="@string/str_fontscolor"
 android:title
="@string/str_fontscolor" 
/>

 

 

Tip:自己封装控件不论是自定义控件也好,preference 也好在XML里面都是无法智能提示的,只要自己把握好输入的属性准确无误就行。

完整代码如下:

 

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(
0
0
, 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
0
100
0
,
                        mHSVColors, 
null
, Shader.TileMode.CLAMP));
            }
            canvas.drawOval(
new
 RectF(
-
r, 
-
r, r, r), mPaint);
            canvas.drawCircle(
0
0
, 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(
0
0
, 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 
<= 
0
) {
                
return
 colors[
0
];
            }
            
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 
< 
0
) {
                        c0 
=
 mHSVColors[
0
];
                        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 
< 
0
) {
                        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);
    }
}

完。      

 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/393621,如需转载请自行联系原作者

你可能感兴趣的文章
设备树
查看>>
使用WindowManager添加您自己的自定义视图
查看>>
Linux内核态抢占机制分析【转】
查看>>
ASP.NET2.0中用ICallbackEventHandler实现客户端与服务器端异步交互
查看>>
关于JFace中的TableViewer和TreeViewer中的
查看>>
Hadoop MapReduce概念学习系列之十分钟看透MapReduce(十一)
查看>>
[C#]C#补习——类型和操作符—PART2
查看>>
链表常见的问题【转】
查看>>
Outlook HTML渲染引擎
查看>>
进程的切换和系统的一般执行过程【转】
查看>>
C语言:创建动态单向链表,创建完成后,输出每一个节点的数据信息。
查看>>
MVC3 上传文件
查看>>
在windows下使用eclipes连接linux下的Hadoop集群
查看>>
URAL 1141. RSA Attack RSA加密演算法
查看>>
[LeetCode] Count Complete Tree Nodes 求完全二叉树的节点个数
查看>>
深入Java集合学习系列:LinkedHashMap的实现原理
查看>>
JSpider(5):EventSinks,Rules&Resources
查看>>
Linux之sed
查看>>
第 40 章 Asymptote: The Vector Graphics Language
查看>>
一点小疑问
查看>>