android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果。
代码的实现可讲的地方不多,主要是采用了和AlertDialog类似的Builder方式来创建对话框,另外当每个颜色被选择的时候有个按下效果是用纯代码实现的,还有就是可以动态的判断一排可以显示多少个颜色元素。而动画效果我们是使用属性动画实现,如果要做到兼容2.3需要使用第三方库NineOldAndroids来实现属性动画。
源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
package com.jcodecraeer.animatedcolorpickerdialog; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.StateListDrawable; import android.graphics.drawable.shapes.OvalShape; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.animation.OvershootInterpolator; import android.widget.GridLayout; import android.widget.GridLayout.Spec; import android.widget.LinearLayout; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; public class AnimatedColorPickerDialog extends Dialog { Context context; public static final int DIALOG_TYPE_MESSAGE = 0; public static final int DIALOG_TYPE_PROGRESS = 2; public static final int DIALOG_TYPE_ALERT = 3; private ColorClickListener mListener; private AnimatedColorPickerDialog(Context context) { this (context,R.style.CustomTheme); } private AnimatedColorPickerDialog(Context context, int theme){ super (context, theme); this .context = context; } public interface ColorClickListener { void onColorClick(int color); } public void setOnColorClickListener(ColorClickListener l ){ mListener = l; } private int getDarkerColor(int color){ float[] hsv = new float[3]; Color.colorToHSV(color, hsv); // convert to hsv // make darker hsv[1] = hsv[1] + 0.1f; // more saturation hsv[2] = hsv[2] - 0.2f; // less brightness int darkerColor = Color.HSVToColor(hsv); return darkerColor ; } private StateListDrawable getStateDrawable(Drawable normal, Drawable pressed, Drawable focus) { StateListDrawable sd = new StateListDrawable(); sd.addState( new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, focus); sd.addState( new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}, pressed); sd.addState( new int[]{android.R.attr.state_focused}, focus); sd.addState( new int[]{android.R.attr.state_pressed}, pressed); sd.addState( new int[]{android.R.attr.state_enabled}, normal); sd.addState( new int[]{}, normal); return sd; } @SuppressLint( "NewApi" ) public void setnumberOfColums(int columnum, int[] colors) { TableLayout colorTable = (TableLayout)findViewById(R.id.color_group); int rows = colors.length % columnum == 0 ? colors.length / columnum : (colors.length / columnum) + 1; for (int r=0; r < rows; r++) { TableRow tableRow = new TableRow(context); for (int c = 0; c < columnum && (c + r * columnum) < colors.length ; c++) { final View item = new View(context); LayoutParams params = new LayoutParams((int)context.getResources().getDimension(R.dimen.color_circle_size), (int)context.getResources().getDimension(R.dimen.color_circle_size)); item.setLayoutParams(params); ShapeDrawable drawableNormal = new ShapeDrawable ( new OvalShape ()); drawableNormal.getPaint().setColor(colors[r * columnum + c]); ShapeDrawable drawablePress = new ShapeDrawable ( new OvalShape ()); drawablePress.getPaint().setColor(getDarkerColor(colors[r * columnum + c])); ShapeDrawable drawableFocus = new ShapeDrawable ( new OvalShape ()); drawableFocus.getPaint().setColor(getDarkerColor(colors[r * columnum + c])); item.setBackground(getStateDrawable(drawableNormal, drawablePress, drawableFocus)); item.setTag(Integer.valueOf(colors[r * columnum + c])); item.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(View view){ if (mListener != null ){ Integer colorHexInObject = (Integer)item.getTag(); mListener.onColorClick(colorHexInObject.intValue()); dismiss(); } } }); LinearLayout itemContainer = new LinearLayout(context); TableRow.LayoutParams pa = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT); pa.setMargins(0, 0, 0, 10); itemContainer.setLayoutParams(pa); itemContainer.addView(item); tableRow.addView(itemContainer); } colorTable.addView(tableRow); } //视差效果动画效果 TextView dialogTitleText = (TextView)findViewById(R.id.dialog_title); dialogTitleText.setTranslationX(-colorTable.getWidth()); final AnimatorSet localAnimatorSet = new AnimatorSet(); ObjectAnimator localObjectAnimator1 = ObjectAnimator.ofFloat(dialogTitleText, "translationX" , -colorTable.getWidth(),0); localObjectAnimator1.setDuration(1200); localObjectAnimator1.setInterpolator( new OvershootInterpolator(1.2F)); localAnimatorSet.play(localObjectAnimator1); colorTable.setTranslationX(-colorTable.getWidth()); ObjectAnimator localObjectAnimator2 = ObjectAnimator.ofFloat(colorTable, "translationX" , -colorTable.getWidth(),0); localObjectAnimator2.setDuration(1200); localObjectAnimator2.setInterpolator( new OvershootInterpolator(1.2F)); localAnimatorSet.play(localObjectAnimator2).after(100); localAnimatorSet.start(); } public static class Builder { private Context context; private ColorClickListener mListener; private int[] colors; private String title; public Builder(Context context) { this .context = context; } public Builder setOnColorClickListener(ColorClickListener l ){ mListener = l; return this ; } public Builder setColors(int[] c) { colors = c; return this ; } public Builder setTitle(String t) { title = t; return this ; } @SuppressLint( "NewApi" ) public AnimatedColorPickerDialog create() { // instantiate the dialog with the custom Theme final AnimatedColorPickerDialog dialog = new AnimatedColorPickerDialog(context,R.style.CustomTheme); dialog.setContentView(R.layout.color_picker_dialog_layout); final TableLayout colorTable= (TableLayout)dialog.findViewById(R.id.color_group); colorTable.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { colorTable.getViewTreeObserver() .removeGlobalOnLayoutListener( this ); int leftWidth = (colorTable.getWidth() - colorTable.getPaddingLeft() * 2) % (int)context.getResources().getDimension(R.dimen.color_circle_size); int tempColums = (colorTable.getWidth() - colorTable.getPaddingLeft() * 2) / (int)context.getResources().getDimension(R.dimen.color_circle_size); if (leftWidth < (tempColums - 1) * 1) { tempColums = tempColums -1; } dialog.setnumberOfColums(tempColums, colors); } }); dialog.setOnColorClickListener(mListener); TextView titleView = (TextView)dialog.findViewById(R.id.dialog_title); titleView.setText(title); View closebutton = dialog.findViewById(R.id.close_button); closebutton.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(View view){ dialog.dismiss(); } }); dialog.setCanceledOnTouchOutside( true ); return dialog; } } } |
dialog的xml代码color_picker_dialog_layout.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
<?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@+id/content_layout" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_gravity= "center" android:gravity= "center" android:background= "#f4f4f4" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:orientation= "vertical" android:paddingLeft= "10dip" android:paddingRight= "10dip" android:paddingTop= "5dip" android:paddingBottom= "5dip" > <RelativeLayout android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:gravity= "center" > <TextView android:id= "@+id/dialog_title" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "选择一个颜色主题" android:textColor= "#333333" android:textStyle= "bold" android:textSize= "18dip" android:layout_alignParentLeft= "true" android:layout_centerVertical= "true" /> <ImageButton android:id= "@+id/close_button" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:gravity= "center" android:src= "@drawable/ic_action_cancel" android:background= "#00000000" android:layout_alignParentRight= "true" /> </RelativeLayout> </LinearLayout> <TableLayout android:padding= "10dip" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:stretchColumns= "*" android:id= "@+id/color_group" > </TableLayout> </LinearLayout> |
使用:
1
2
3
4
5
6
7
8
9
10
11
|
public void openColorDialog(View v) { new AnimatedColorPickerDialog.Builder(MainActivity. this ) .setTitle( "选择一种颜色" ) .setColors(styleColors) .setOnColorClickListener( new AnimatedColorPickerDialog.ColorClickListener() { @Override public void onColorClick(int color) { colorDisplayView.setBackgroundColor(color); } }).create().show(); } |
demo下载地址:https://github.com/jianghejie/AnimatedColorPickerDialog