Android 颜色渲染(一) 颜色选择器 ColorPickerDialog剖析

Android 颜色选择器之ColorPickerDialog剖析

      有这样一个需求,可以让用户自定义背景颜色,这就需要提供一个颜色选择器给用户.

      在Android 中,如何实现这样的功能呢,遇到这种需求是,先查看一下ApiDemos,是否已经有相关的实例,果然,找到了一个可以参考的demo:ColorPickerDialog

我已经把apidemos导入到eclipse中,请看截图:


我们要找的就是这个ColorPickerDialog,在com.example.android.apis.graphics目录下,是一个颜色选择器对话框,在哪个demo中使用的呢,References下之后,发现是在

FingerPaint,也就是涂鸦的例子中:

                                                              


接下来还是直接看代码:

package com.example.android.apis.graphics;

import android.os.Bundle;
import android.app.Dialog;
import android.content.Context;
import android.graphics.*;
import android.view.MotionEvent;
import android.view.View;

public class ColorPickerDialog extends Dialog {

    public interface OnColorChangedListener {
        void colorChanged(int color);
    }

    private OnColorChangedListener mListener;
    private int mInitialColor;

    private static class ColorPickerView extends View {//颜色选择器自定义View
        private Paint mPaint;//渐变色环画笔 
        private Paint mCenterPaint;//中间圆画笔  
        private final int[] mColors;//渐变色环颜色
        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(32);
            
            //初始化中心园画笔
            mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mCenterPaint.setColor(color);
            mCenterPaint.setStrokeWidth(5);
        }
        
        private boolean mTrackingCenter;
        private boolean mHighlightCenter;

        @Override 
        protected void onDraw(Canvas canvas) {
            float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;
            
            //移动中心
            canvas.translate(CENTER_X, CENTER_X);
            //画出色环和中心园
            canvas.drawOval(new RectF(-r, -r, r, r), mPaint);            
            canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
            
            if (mTrackingCenter) {
                int c = mCenterPaint.getColor();
                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);
            }
        }
        
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
        }
        
        private static final int CENTER_X = 100;
        private static final int CENTER_Y = 100;
        private static final int CENTER_RADIUS = 32;

        private int floatToByte(float x) {
            int n = java.lang.Math.round(x);
            return n;
        }
        private int pinToByte(int n) {
            if (n < 0) {
                n = 0;
            } else if (n > 255) {
                n = 255;
            }
            return n;
        }
        
        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 int rotateColor(int color, float rad) {
            float deg = rad * 180 / 3.1415927f;
            int r = Color.red(color);
            int g = Color.green(color);
            int b = Color.blue(color);
            
            ColorMatrix cm = new ColorMatrix();
            ColorMatrix tmp = new ColorMatrix();

            cm.setRGB2YUV();
            tmp.setRotate(0, deg);
            cm.postConcat(tmp);
            tmp.setYUV2RGB();
            cm.postConcat(tmp);
            
            final float[] a = cm.getArray();

            int ir = floatToByte(a[0] * r +  a[1] * g +  a[2] * b);
            int ig = floatToByte(a[5] * r +  a[6] * g +  a[7] * b);
            int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);
            
            return Color.argb(Color.alpha(color), pinToByte(ir),
                              pinToByte(ig), pinToByte(ib));
        }
        
        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 {
                        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 ColorPickerDialog(Context context,
                             OnColorChangedListener listener,
                             int initialColor) {
        super(context);
        
        mListener = listener;
        mInitialColor = initialColor;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        OnColorChangedListener l = new OnColorChangedListener() {
            public void colorChanged(int color) {
                mListener.colorChanged(color);
                dismiss();
            }
        };

        setContentView(new ColorPickerView(getContext(), l, mInitialColor));
        setTitle("Pick a Color");
    }
}

        当然,目前的这个例子还有一定的局限,比如无黑白色,只能选择大概的颜色区间(后续会讲解). 当然只要把这个demo研究好后,具体的改进不是问题.


另附上ApiDemos下载地址: http://download.csdn.net/detail/t12x3456/6007883

如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456


  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您可以使用 Ant Design 的 `<ColorPicker>` 组件来实现更改背景颜色的功能。以下是一个示例代码: ```jsx import React, { useState } from "react"; import { ColorPicker } from "antd"; function ColorPickerDemo() { const [backgroundColor, setBackgroundColor] = useState("#ffffff"); const handleColorChange = (color) => { setBackgroundColor(color.hex); }; return ( <div style={{ backgroundColor }}> <h1>Background Color</h1> <ColorPicker color={backgroundColor} onChange={handleColorChange} /> </div> ); } export default ColorPickerDemo; ``` 在上面的代码中,我们首先引入了 `<ColorPicker>` 组件,然后使用 `useState` 钩子来定义一个 `backgroundColor` 状态,用于保存背景颜色。接着,我们定义了一个 `handleColorChange` 函数,用于处理颜色改变事件,并将新的背景颜色保存到状态中。最后,在渲染函数中,我们将背景颜色设置为 `<div>` 元素的样式,并将 `<ColorPicker>` 组件放置在页面上,以便用户可以选择新的背景颜色。 请注意,上面的示例代码仅供参考,您可以根据自己的需求进行修改和定制。 ### 回答2: antd是一个基于React的UI组件库,它提供了丰富的界面组件供开发者使用。其中,antd的颜色选择器组件可以用来实现更改背景颜色的功能。 首先,我们需要在项目中引入antd的颜色选择器组件。可以通过npm安装antd,然后在代码中引入ColorPicker组件。 接下来,在需要使用颜色选择器的地方,我们可以使用ColorPicker组件来渲染一个颜色选择器。 例如,在一个React函数组件中,我们可以这样写: ```jsx import React, { useState } from 'react'; import { ColorPicker } from 'antd'; const MyComponent = () => { const [bgColor, setBgColor] = useState('#ffffff'); const handleColorChange = (color) => { setBgColor(color); } return ( <div style={{ backgroundColor: bgColor }}> <h1>背景颜色选择器</h1> <ColorPicker color={bgColor} onChange={handleColorChange} /> </div> ); } export default MyComponent; ``` 在上面的例子中,我们使用useState来管理背景颜色的状态,初始值为白色。然后,我们定义了一个handleColorChange函数来处理颜色选择器的变化事件。当颜色选择器颜色发生变化时,handleColorChange将被调用,更新背景颜色的状态。 最后,在组件的返回部分,我们将backgroundColor设置为当前背景颜色的值,这样就可以实现根据颜色选择器选择的颜色来动态改变背景颜色了。 以上就是使用antd颜色选择器实现更改背景颜色的简单示例,你可以根据自己的具体需求进行拓展和调整。 ### 回答3: antd是一个基于React的UI组件库,其中包括了丰富的组件和样式,包括颜色选择器。 要实现更改背景颜色,我们可以使用antd中的ColorPicker组件。首先,在React组件中引入ColorPicker组件: ```jsx import { ColorPicker } from 'antd'; class App extends React.Component { constructor(props) { super(props); this.state = { bgColor: '#ffffff' // 初始化背景颜色为白色 }; } handleColorChange = (color) => { this.setState({ bgColor: color.hex }); // 当颜色选择器颜色改变时,更新背景颜色状态 } render() { return ( <div style={{ backgroundColor: this.state.bgColor }}> <ColorPicker onChange={this.handleColorChange} /> // 将handleColorChange函数作为ColorPicker组件的onChange事件处理函数 </div> ); } } export default App; ``` 在上面的代码中,我们在组件的state中定义了一个`bgColor`状态,用于存储背景颜色。在构造函数中,我们将`bgColor`初始化为白色`#ffffff`。 然后,我们实现了一个`handleColorChange`方法,用于在颜色选择器颜色改变时更新`bgColor`状态。在render方法中,我们将`bgColor`应用在`div`元素的`backgroundColor`样式中,使其成为背景颜色。 最后,将`handleColorChange`函数作为`ColorPicker`组件的`onChange`事件处理函数传递,可以使得当颜色选择器颜色改变时,调用`handleColorChange`方法。 通过以上实现,我们可以使用antd的颜色选择器组件来实现更改背景颜色的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值