一个带动画效果的颜色选择对话框控件AnimatedColorPickerDialog
ChrWingfiel
9年前
来自: http://www.jcodecraeer.com//a/anzhuokaifa/androidkaifa/2014/0930/1721.html
android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果。
代码的实现可讲的地方不多,主要是采用了和AlertDialog类似的Builder方式来创建对话框,另外当每个颜色被选择的时候有个按下效果是用纯代码实现的,还有就是可以动态的判断一排可以显示多少个颜色元素。而动画效果我们是使用属性动画实现,如果要做到兼容2.3需要使用第三方库NineOldAndroids来实现属性动画。
源码如下:
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:
<?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>
使用:
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