最近在写的项目Awosome-Campus中需要用到颜色选择器,用于更改主题,自己写了个。另外我想将它用于之前的项目闲暇(Leisure)中,干脆就将它单独分离出来了。代码规范,添加了详细注释。后来又想想为什么不尝试将它打包发布,说干就干。过程曲折,除夕前夜搞到三点多都没有弄好,第二天(过年)下午四五点才算发布成功。不过这篇博文不是讲怎样打包发布,而是主要介绍它的实现。

我是照着酷安的颜色选择器做的,使用了下,感觉用Dialog比较方便,只要实现中间的View,其他的逻辑就不用管了。这个自定义View支持自由添加颜色,自由选择颜色以及排版。最终做出的效果:


实现思路

1. 将它进行分解,首先实现单个的圆点:

1) 继承View,绘制圆形,同时根据当前原点是否被选中决定是否绘制"对勾"

2) 圆形绘制有现成的方法,对勾根据圆形半径计算,固定三个点连线即可。这里需要注意的是"对勾"的颜色,默认为 白色,如果原点本身颜色偏白(rgb值接近0) 就绘制黑色的"勾"。

3) 然后是布局,根布局是垂直方向的线性布局,然后以行为单位一行一行地添加到根布局中。这里的"行"是一个水平

方向的线性布局,每一行再添加规定数量的"圆点",圆点之间加margin【这里实现有点技巧】

4) 添加一个接口,用于对点击进行响应,这里需要获取选中的颜色值。实现就是经常用的listener了(观察者模式? ),

View本身有个onClickListener,实现它,在onClick中调用我这个接口即可。同时在选中新的颜色的时候也要将之

前“被选中的圆点”置为非选中状态。

5)最后封装成一个View add 到 AlterDialog中就可以了,AlterDialog的宽高也需要根据圆点数量什么的计算一下。


放下圆点(ColorButton)的代码,其他代码见文末GitHub:

** * Created by MummyDing on 16-2-4. * GitHub: https://github.com/MummyDing * Blog: http://blog.csdn.net/mummyding */public class ColorButton extends View {    private Context mContext;    /**     * color of the ColorButton,default RED.     */    private int mColor = Color.RED;    /**     * radius of the ColorButton     */    private int mRadius;    private boolean isChecked = false;    private Paint mPaint;    /**     * paddingHorizontal is relative to the "circle" inside ColorButton (Horizontal)     */    private int paddingHorizontal;    /**     *  paddingVertical is relative to the "circle" inside ColorButton (Vertical)     */    private int paddingVertical;    /**     * real width of ColorButton (including paddingHorizontal)     * width = 2*(mRadius + paddingHorizontal)     */    private int width;    /**     * real height of ColorButton (including paddingVertical)     * height = 2*(mRadius + paddingVertical)     */    private int height;    /**     * set size to defaultWidth if user has not specified     * unit: dip     */    private int defaultWidth = 30;    public ColorButton(Context context, int color) {        super(context);        mContext = context;        mColor = color;        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStrokeWidth(5);        defaultWidth = DisplayUtil.dip2px(mContext,defaultWidth);    }    public ColorButton(Context context) {        this(context,Color.RED);    }    public ColorButton(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStrokeWidth(5);        defaultWidth = DisplayUtil.dip2px(mContext,defaultWidth);    }    public ColorButton(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStrokeWidth(5);        defaultWidth = DisplayUtil.dip2px(mContext,defaultWidth);    }    /**     * ColorButton is not support self-define padding     * @param widthMeasureSpec     * @param heightMeasureSpec     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        if(widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){            setMeasuredDimension(defaultWidth,defaultWidth);        }else if(widthMode == MeasureSpec.AT_MOST){            setMeasuredDimension(defaultWidth,heightSize);        }else if(heightMode == MeasureSpec.AT_MOST){            setMeasuredDimension(widthSize,defaultWidth);        }    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        width = getWidth();        height = getHeight();        mRadius = Math.min(width,height)/2;        paddingHorizontal = (width - mRadius*2)/2;        paddingVertical = (height - mRadius*2)/2;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        drawCircle(canvas);        if(isChecked()){            drawCheck(canvas);        }    }    private void drawCircle(Canvas canvas){        mPaint.setColor(mColor);        canvas.drawCircle(paddingHorizontal + width/2,paddingVertical + height/2,mRadius,mPaint);    }    private void drawCheck(Canvas canvas){        if(-40 <mColor && mColor< 40){            mPaint.setColor(Color.BLACK);        }else {            mPaint.setColor(Color.WHITE);        }        Point p1 = new Point(paddingHorizontal + (int)(0.3 * (double) mRadius),paddingVertical + mRadius);        Point p2 = new Point(paddingHorizontal + (int)(0.8 * (double) mRadius),paddingVertical + (int)(1.4 * (double) mRadius));        Point p3 = new Point(paddingHorizontal + (int)(1.4 * (double)mRadius),paddingVertical +(int)(0.4 * (double) mRadius));        canvas.drawLine(p1.x,p1.y,p2.x,p2.y,mPaint);        canvas.drawLine(p2.x,p2.y,p3.x,p3.y,mPaint);    }    public boolean isChecked() {        return isChecked;    }    public void setChecked(boolean checked) {        isChecked = checked;        invalidate();    }    public int getmColor() {        return mColor;    }}


GitHub项目地址:https://github.com/MummyDing/ColorPickerDialog[觉得好的话给个star吧~_~]

其他完整开源项目:https://github.com/MummyDing/Leisure

出处:http://blog.csdn.net/mummyding/article/




更多相关文章

  1. 【凯子哥带你学Android】Andriod性能优化之列表卡顿——以“简书
  2. Android多屏幕适配及自适应解决方案
  3. Android布局方式(FrameLayout)学习
  4. Android图形图画学习(11)——颜色相关
  5. Android:修图技术之滤镜效果实现及原理分析——ColorMatrix
  6. 自定义Android带图片的按钮
  7. android Item 滑动删除核心逻辑实现
  8. android滑动切换屏幕(扒的是launcher2/workspace的源码)
  9. Android(安卓)Matrix矩阵原理详解

随机推荐

  1. ScrollView嵌套RecyclerView冲突解决
  2. Android(安卓)Intent调用大全
  3. Android(安卓)binder 原理及实现机制
  4. Android 编译提示R文件找不到
  5. 導入android項目出錯問題解決
  6. Android Touch事件
  7. android installd分析
  8. Android Jetpack之Lifecycle的源码分析
  9. Android(安卓)四个步骤集成EventBus事件
  10. 2011.09.01(5)——— android checkbox自定