Android颜色选择器

news2024/11/15 17:32:53

Android颜色选择器,弹框提示选择颜色。效果如图。点击或者滑动圆环和底部横向渐变色调整颜色,中间圆圈的颜色就是最终选中的颜色。点击圆圈确认颜色。

使用

    //颜色选择Dialog
    private void showColorPickDialog(int position, int colorInt){
        ColorPickerDialog dialog = new ColorPickerDialog(context, colorInt,
                "弹框的title",
                new ColorPickerDialog.OnColorChangedListener() {
                    @Override
                    public void colorChanged(int color) {
                        //todo 获取颜色之后的页面设置
                    }
                });
        dialog.show();
    }

自定义的ColorPickerDialog。这个是在别的文章看到的,我自己添加了title的内容。具体网址找到之后添加。

package com.....dialog;

import android.app.Dialog;
import android.content.Context;
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.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

public class ColorPickerDialog extends Dialog {
    private final boolean debug = true;
    private final String TAG = "ColorPicker";

    Context context;
    private String title;//标题
    private int mInitialColor;//初始颜色
    private OnColorChangedListener mListener;

    /**
     * 初始颜色黑色
     * @param context
     * @param title 对话框标题
     * @param listener 回调
     */
    public ColorPickerDialog(Context context, String title,
                             OnColorChangedListener listener) {
        this(context, Color.BLACK, title, listener);
    }

    /**
     *
     * @param context
     * @param initialColor 初始颜色
     * @param title 标题
     * @param listener 回调
     */
    public ColorPickerDialog(Context context, int initialColor,
                             String title, OnColorChangedListener listener) {
        super(context);
        this.context = context;
        mListener = listener;
        mInitialColor = initialColor;
        this.title = title;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowManager manager = getWindow().getWindowManager();
        int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);
        int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);
        ColorPickerView myView = new ColorPickerView(context, height, width);
        setContentView(myView);
        setTitle(title);
    }

    private class ColorPickerView extends View {
        private Paint mPaint;//渐变色环画笔
        private Paint mCenterPaint;//中间圆画笔
        private Paint mLinePaint;//分隔线画笔
        private Paint mRectPaint;//渐变方块画笔
        private Paint mTitlePaint;//标题画笔

        private Shader rectShader;//渐变方块渐变图像
        private float rectLeft;//渐变方块左x坐标
        private float rectTop;//渐变方块右x坐标
        private float rectRight;//渐变方块上y坐标
        private float rectBottom;//渐变方块下y坐标

        private final int[] mCircleColors;//渐变色环颜色
        private final int[] mRectColors;//渐变方块颜色
        private final int mTitleColor;//标题颜色

        private int mHeight;//View高
        private int mWidth;//View宽
        private float r;//色环半径(paint中部)
        private float centerRadius;//中心圆半径
        private float titleX;//标题起始位置
        private float titleY;//标题起始位置

        private boolean downInCircle = true;//按在渐变环上
        private boolean downInRect;//按在渐变方块上
        private boolean highlightCenter;//高亮
        private boolean highlightCenterLittle;//微亮

        public ColorPickerView(Context context, int height, int width) {
            super(context);
            this.mHeight = height - 36;
            this.mWidth = width;
            setMinimumHeight(height - 36);
            setMinimumWidth(width);

            //渐变色环参数
            mCircleColors = new int[] {0xFFFF0000, 0xFFFF00FF, 0xFF0000FF,
                    0xFF00FFFF, 0xFF00FF00,0xFFFFFF00, 0xFFFF0000};
            Shader s = new SweepGradient(0, 0, mCircleColors, null);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setShader(s);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(50);
            r = width / 2 * 0.7f - mPaint.getStrokeWidth() * 0.5f;

            //中心圆参数
            mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mCenterPaint.setColor(mInitialColor);
            mCenterPaint.setStrokeWidth(5);
            centerRadius = (r - mPaint.getStrokeWidth() / 2 ) * 0.7f;

            //边框参数
            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mLinePaint.setColor(Color.parseColor("#72A1D1"));
            mLinePaint.setStrokeWidth(4);

            //黑白渐变参数
            mRectColors = new int[]{0xFF000000, mCenterPaint.getColor(), 0xFFFFFFFF};
            mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRectPaint.setStrokeWidth(5);
            rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;
            rectTop = r + mPaint.getStrokeWidth() * 0.5f +
                    mLinePaint.getStrokeMiter() * 0.5f + 15;
            rectRight = r + mPaint.getStrokeWidth() * 0.5f;
            rectBottom = rectTop + 50;

            //标题参数
            mTitleColor = 0xFF333333;
            mTitlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mTitlePaint.setColor(mTitleColor);
            mTitlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mTitlePaint.setTextSize(40);
            mTitlePaint.setStrokeWidth(2);
            float titleLen = mTitlePaint.measureText(title);
            titleX = (width - titleLen) /2;
            titleY = 70;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            //画标题
            canvas.drawText(title, titleX, titleY, mTitlePaint);
            //移动中心
            canvas.translate(mWidth / 2, mHeight / 2 - 50);
            //画中心圆
            canvas.drawCircle(0, 0, centerRadius,  mCenterPaint);
            //是否显示中心圆外的小圆环
            if (highlightCenter || highlightCenterLittle) {
                int c = mCenterPaint.getColor();
                mCenterPaint.setStyle(Paint.Style.STROKE);
                if(highlightCenter) {
                    mCenterPaint.setAlpha(0xFF);
                }else if(highlightCenterLittle) {
                    mCenterPaint.setAlpha(0x90);
                }
                canvas.drawCircle(0, 0,
                        centerRadius + mCenterPaint.getStrokeWidth(),  mCenterPaint);

                mCenterPaint.setStyle(Paint.Style.FILL);
                mCenterPaint.setColor(c);
            }
            //画色环
            canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
            //画黑白渐变块
            if(downInCircle) {
                mRectColors[1] = mCenterPaint.getColor();
            }
            rectShader = new LinearGradient(rectLeft, 0, rectRight, 0, mRectColors, null, Shader.TileMode.MIRROR);
            mRectPaint.setShader(rectShader);
            canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);
            float offset = mLinePaint.getStrokeWidth() / 2;
            canvas.drawLine(rectLeft - offset, rectTop - offset * 2,
                    rectLeft - offset, rectBottom + offset * 2, mLinePaint);//左
            canvas.drawLine(rectLeft - offset * 2, rectTop - offset,
                    rectRight + offset * 2, rectTop - offset, mLinePaint);//上
            canvas.drawLine(rectRight + offset, rectTop - offset * 2,
                    rectRight + offset, rectBottom + offset * 2, mLinePaint);//右
            canvas.drawLine(rectLeft - offset * 2, rectBottom + offset,
                    rectRight + offset * 2, rectBottom + offset, mLinePaint);//下
            super.onDraw(canvas);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX() - mWidth / 2;
            float y = event.getY() - mHeight / 2 + 50;
            boolean inCircle = inColorCircle(x, y,
                    r + mPaint.getStrokeWidth() / 2, r - mPaint.getStrokeWidth() / 2);
            boolean inCenter = inCenter(x, y, centerRadius);
            boolean inRect = inRect(x, y);

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downInCircle = inCircle;
                    downInRect = inRect;
                    highlightCenter = inCenter;
                case MotionEvent.ACTION_MOVE:
                    if(downInCircle && inCircle) {//down按在渐变色环内, 且move也在渐变色环内
                        float angle = (float) Math.atan2(y, x);
                        float unit = (float) (angle / (2 * Math.PI));
                        if (unit < 0) {
                            unit += 1;
                        }
                        mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));
                        if(debug) Log.v(TAG, "色环内, 坐标: " + x + "," + y);
                    }else if(downInRect && inRect) {//down在渐变方块内, 且move也在渐变方块内
                        mCenterPaint.setColor(interpRectColor(mRectColors, x));
                    }
                    if(debug) Log.v(TAG, "[MOVE] 高亮: " + highlightCenter + "微亮: " + highlightCenterLittle + " 中心: " + inCenter);
                    if((highlightCenter && inCenter) || (highlightCenterLittle && inCenter)) {//点击中心圆, 当前移动在中心圆
                        highlightCenter = true;
                        highlightCenterLittle = false;
                    } else if(highlightCenter || highlightCenterLittle) {//点击在中心圆, 当前移出中心圆
                        highlightCenter = false;
                        highlightCenterLittle = true;
                    } else {
                        highlightCenter = false;
                        highlightCenterLittle = false;
                    }
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    if(highlightCenter && inCenter) {//点击在中心圆, 且当前启动在中心圆
                        if(mListener != null) {
                            mListener.colorChanged(mCenterPaint.getColor());
                            ColorPickerDialog.this.dismiss();
                        }
                    }
                    if(downInCircle) {
                        downInCircle = false;
                    }
                    if(downInRect) {
                        downInRect = false;
                    }
                    if(highlightCenter) {
                        highlightCenter = false;
                    }
                    if(highlightCenterLittle) {
                        highlightCenterLittle = false;
                    }
                    invalidate();
                    break;
            }
            return true;
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(mWidth, mHeight);
        }

        /**
         * 坐标是否在色环上
         * @param x 坐标
         * @param y 坐标
         * @param outRadius 色环外半径
         * @param inRadius 色环内半径
         * @return
         */
        private boolean inColorCircle(float x, float y, float outRadius, float inRadius) {
            double outCircle = Math.PI * outRadius * outRadius;
            double inCircle = Math.PI * inRadius * inRadius;
            double fingerCircle = Math.PI * (x * x + y * y);
            if(fingerCircle < outCircle && fingerCircle > inCircle) {
                return true;
            }else {
                return false;
            }
        }

        /**
         * 坐标是否在中心圆上
         * @param x 坐标
         * @param y 坐标
         * @param centerRadius 圆半径
         * @return
         */
        private boolean inCenter(float x, float y, float centerRadius) {
            double centerCircle = Math.PI * centerRadius * centerRadius;
            double fingerCircle = Math.PI * (x * x + y * y);
            if(fingerCircle < centerCircle) {
                return true;
            }else {
                return false;
            }
        }

        /**
         * 坐标是否在渐变色中
         * @param x
         * @param y
         * @return
         */
        private boolean inRect(float x, float y) {
            if( x <= rectRight && x >=rectLeft && y <= rectBottom && y >=rectTop) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * 获取圆环上颜色
         * @param colors
         * @param unit
         * @return
         */
        private int interpCircleColor(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);
        }

        /**
         * 获取渐变块上颜色
         * @param colors
         * @param x
         * @return
         */
        private int interpRectColor(int colors[], float x) {
            int a, r, g, b, c0, c1;
            float p;
            if (x < 0) {
                c0 = colors[0];
                c1 = colors[1];
                p = (x + rectRight) / rectRight;
            } else {
                c0 = colors[1];
                c1 = colors[2];
                p = x / rectRight;
            }
            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);
            return Color.argb(a, r, g, b);
        }

        private int ave(int s, int d, float p) {
            return s + Math.round(p * (d - s));
        }
    }

    /**
     * 回调接口
     * @author <a href="clarkamx@gmail.com">LynK</a>
     *
     * Create on 2012-1-6 上午8:21:05
     *
     */
    public interface OnColorChangedListener {
        /**
         * 回调函数
         * @param color 选中的颜色
         */
        void colorChanged(int color);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getmInitialColor() {
        return mInitialColor;
    }

    public void setmInitialColor(int mInitialColor) {
        this.mInitialColor = mInitialColor;
    }

    public OnColorChangedListener getmListener() {
        return mListener;
    }

    public void setmListener(OnColorChangedListener mListener) {
        this.mListener = mListener;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1411630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat session复制及session共享技术

目录 1、环境 2、配置测试页面 3、配置session共享 前言&#xff1a; 为什么要做session复制或共享 实现Session复制或Session共享的目的是为了在多个Tomcat实例之间实现Session的无缝转移和共享&#xff0c;以提供更高的可伸缩性、负载均衡和容错性。以下是一些原因&#x…

浅谈DNS的工作原理及其作用

DNS&#xff0c;全称为Domain Name System&#xff0c;即域名系统&#xff0c;是一种用于将域名和IP地址相互映射的分布式数据库系统。它将可读的域名转换为对应的IP地址&#xff0c;使得用户可以更方便地通过域名来访问网络上的资源。今天锐成就简单探讨一下DNS的工作原理及其…

Redis 面试题 | 11.精选Redis高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Java服务端使用freemarker+wkhtmltoimage生成Echart图片

目录 1.通过 freemarker 将ftl转成html 1.1 freemarker 手册: 1.2 添加freemarker maven依赖 1.3 添加 echart-test.ftl 模版文件 1.4 添加 FreemarkerTool 工具类 1.5 添加测试main方法 1.6 运行,生成echart-test-时间戳.html 文件 2. 通过wkhtmltoimage将html 转为p…

Flink max maxby区别

max只会显示指定字段的大小变化&#xff0c;而maxBy会显示其他字段的变化。 max&#xff1a;取指定字段的当前的最大值&#xff0c;如果有多个字段&#xff0c;其他非比较字段&#xff0c;以第一条为准。 maxBy&#xff1a;取指定字段的当前的最大值&#xff0c;如果有多个字段…

企业出海数据合规:GDPR下数据出境的条件

一、GDPR对数据出镜的规制 GDPR第五章集中规定了数据跨境流动的形式&#xff0c;总的来说给出了三种个人数据出境的条件&#xff0c;分别是基于充分决定的数据传输&#xff1b;基于采取适当保障措施的数据传输&#xff1b;以及基于特殊情况的减损条款&#xff0c;分别对应的是…

windows下git pull超时,ping不通github

报错 ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. 解决办法 修改hosts 最后加一行&#xff0c;文件位置&#xff1a;…

Leetcode:二分搜索树层次遍历

题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,…

16、Kafka ------ SpringBoot 整合 Kafka (配置 Kafka 属性 及对应的 属性处理类 解析)

目录 配置 Kafka 及对应的 属性处理类配置KafkaKafka配置属性的约定代码演示生产者相关的配置消费者相关的配置 代码&#xff08;配置文件&#xff09;application.properties 配置 Kafka 及对应的 属性处理类 配置Kafka spring.kafka.* 开头的配置属性&#xff0c;这些属性将由…

MSB20M-ASEMI小功率家电专用MSB20M

编辑&#xff1a;ll MSB20M-ASEMI小功率家电专用MSB20M 型号&#xff1a;MSB20M 品牌&#xff1a;ASEMI 封装&#xff1a;UMSB-4 最大重复峰值反向电压&#xff1a;1000V 最大正向平均整流电流(Vdss)&#xff1a;2A 功率(Pd)&#xff1a;50W 芯片个数&#xff1a;4 引…

OpenHarmony开发——GN快速上手

背景 最近在研究鸿蒙操作系统的开源项目OpenHarmony&#xff0c;该项目使用了GNNinja工具链进行配置&#xff0c;编译&#xff0c;于是开始研究GN如何使用。 本文的所有信息均来自GN官网和本人个人体会。 GN快速入门 使用GN GN的主要功能是根据配置文件&#xff08;.gn, BU…

【排序2】-交换排序

&#x1f47b;交换排序 &#x1f384;1、基本思想及特点&#x1f384;2、冒泡排序&#x1f384;3、快速排序&#xff08;挖坑法&#xff09;&#x1f384;4、快速排序优化&#x1f38a;4.1 三数取中法选key&#x1f38a;4.2 递归到小的子区间时&#xff0c;可以考虑使用插入排序…

Linux零碎点

目录 Linux基础命令 1、who&#xff1a; 2、hostname&#xff1a; 3、ifconfig&#xff1a; 4、pwd&#xff1a; 5、cd&#xff1a; 6、exit&#xff1a; 7、shutdown&#xff1a; 8、ls&#xff1a; 9、创建文件夹&#xff1a; 10、touch&#xff1a; 11、cp&#…

Java PDFBox 提取页数、PDF转图片

PDF 提取 使用Apache 的pdfbox组件对PDF文件解析读取和转图片。 Maven 依赖 导入下面的maven依赖&#xff1a; <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.30</version> &l…

实力上榜!安全狗入选《CCSIP 2023中国网络安全行业业全景册(第六版)》多个细项

1月24日&#xff0c;Freebuf发布了《CCSIP 2023中国网络安全行业业全景册&#xff08;第六版&#xff09;》。 作为国内云原生安全领导厂商&#xff0c;安全狗也入选多个细分领域。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;创办于2013年&…

VS2022联合Qt5开发学习10(QT5.12.3联合VTK在VS2022上开发医学图像项目4——ScrollBar控制对比度、切面位置)

这篇博文是接着VS2022联合Qt5开发学习7&#xff08;QT5.12.3联合VTK在VS2022上开发医学图像项目2——十字叉标注&#xff09;-CSDN博客这篇博文延伸开发医学图像的显示渲染相关项目&#xff0c;主要介绍的是在之前显示的图像上增加滑块控制。 用到的内容有&#xff1a; VS2022…

Linux常用命令之文件管理篇

文章目录 前言文件管理命令1、cat 由第一行开始显示文件内容2、ls 列出目录3、cd 切换目录4、mkdir 创建新目录5、touch 创建文件6、 rm 移除文件或目录7、cp 即拷贝文件和目录。8、 mv 移动文件与目录&#xff0c;或修改名称9、 chmod&#xff1a;更改文件9个属性10、chown&am…

Kubernets Deployment详解

因为Pod生命周期是短暂的&#xff0c;一旦运行完成则立即回收&#xff0c;且涉及Pod的创建、自愈、删除等操作比较复杂&#xff0c;所以很少在Kubernetes中直接使用Pod。而是使用更高级的称为Controller&#xff08;控制器&#xff09;的抽象层&#xff0c;来完成对Pod的创建、…

如何解决服务器端口被占用的问题,减少带来的影响

在现代网络环境中&#xff0c;服务器扮演着至关重要的角色&#xff0c;其稳定性和安全性对企业的正常运营具有重要意义。然而&#xff0c;服务器端口被占用的问题却时常困扰着企业网络管理员。本文将深入探讨服务器端口被占用的影响&#xff0c;并提出相应的解决方案。 一、服务…

linux ubuntu下面好用的录屏截图工具kazam 简单好用

kazam可以录屏&#xff0c;可以截图。 安装 apt install kazam使用 开始录制 ctrlmetashiftR 停止&#xff1a; ctrlmetashiftF 保存位置 ~/Videos KKVIEW:一键远控手机电脑