关于安卓颜色选择器的使用(一)
创始人
2025-05-31 17:19:17
0

本文内容为从0-1开发一个颜色选择器,先上效果图
效果图

相关源码文件,将会在文末附上。

效果如图所示。本文将讲述如何自定义一个这样的控件,代码在文末。

思考

(一)实现方式
(二)传递给业务层的数据格式
(三)实现细节

上面三个点,是需要我们去思考的。
(一),这里选择的实现方法,推荐是自定义view,因为这种布局,一般普通的控件,是不支持的。
(二)对于业务层来说,应该做的是,传递颜色数据进入我们的控件,然后控件选择了颜色后,把颜色数据原封不动的传回给业务层,这里选择了String格式作为色值传递,如“#ffffff”。
(三)实现中,使用canvas如何正确绘制圆弧,如何计算真实的角度,象限区间的数据转换,以及坐标数据的转换,点击事件的坐标计算,都是值得思考的问题。

好了,思考完以后,就开始干活。

实现过程

#####(一)定义类
做类似的控件,都是需要有一个大纲思维,就是我这个控件库,给外部暴露了什么方法,我内部又需要如何处理外部传入的数据。所以,要先定义好抽象方法:

(1)控件抽象类:

 interface LibColorCirclePickerApi {fun setColor(color: Array>)fun setLibColorCirclePickerListener(listener: LibColorCirclePickerListener)fun removeLibColorCirclePickerListener()
}

(2)外部监听类:

interface LibColorCirclePickerListener {fun selInfo(info: LibColorSelInfo)}

定义好这些方法,就可以通过继承,具体实现了。

#####(二)自定义view实现绘制色值

这里涉及到canvas绘制的知识,请提前了解。
而如图所示,绘制分为两个层级。一个就是中心圆,另外一个就是色块。

在绘制之前,需要确定以下的变量,方便后续的绘制:
(一)绘制的中心坐标点,x,y点。这里取x/2,y/2。
(二)绘制的半径,这里取最短边的一般作为绘制的半径。
(三)绘制中心圆的半径,通过一定的比率和(二)相乘,得出中心圆的半径。
(四)除中心圆外,剩余的半径长度,这里后续会做平均划分,计算除每层色块的半径长度。
(五)初始化相关中间变量值(如色块坐标集合)

初始相关变量后后,就开始绘制:

绘制中心圆

对于中心圆,这里直接调用canvas的画圆圈方法就行,不再啰嗦

绘制色块

对于色块,首先要明确,你的色块有多少层,这里就决定了每层色块的半径长度。这里的多少层,是通过外部传入的二维数组决定的。对于传入的二维数组,一维决定层级,二维就是一维下的色块数组。

通过上述的了解,就可以通过 “剩余半径” 除以 “色块层数” 即可得出 “每层色块半径长度”。

再通过 360 除以 “每层色块数量”,即可得出每个色块所占的角度。

最后通过设置画笔的strokeWidth,就可以进行绘制。

最后,把绘制过程中产生的“半径范围值”,“角度范围值”,“色值”通过中间变量保存,供以后续的触摸事件调用。

ps:

这里有个实现细节,就是关于Paint的strokeWidth。实际是基于绘制坐标两端扩展的。例如,绘制一条直线,那就会在Y坐标两端拓展,如 (x,y)(0,10),strokeWidth是10,那么直角边宽度就会基于(0,5)-(0,15)中间。

所以,设置strokeWidth后绘制,需要预留绘制实现中的位置。

触摸事件

对于触摸事件,需要在onTouchEvent中进行处理,父类方法重新如下:

    override fun onTouchEvent(event: MotionEvent?): Boolean {when (event?.action) {MotionEvent.ACTION_DOWN -> {}MotionEvent.ACTION_MOVE -> {}MotionEvent.ACTION_UP -> {val currentX = event.xval currentY = event.ydealWithUpEvent(currentX, currentY)}MotionEvent.ACTION_CANCEL -> {}}return true}

这里通过return true,把所有事件都拦截到本view进行处理了。

设想一下,有了中心坐标,和点击时候的x,y坐标。是不是可以得出一个“象限区间”的逻辑?然后再通过数学公式tan方法,即可得出对应的角度。

角度有了,象限有了,就可以换算出最后的真正点击角度,还有点击坐标点的半径。核心代码如下:

    /*** 处理手势抬起事件* */private fun dealWithUpEvent(currentX: Float, currentY: Float) {//判断象限val trainX = (currentX - mCenterX)val trainY = (mCenterY - currentY)//求半径长度val x = abs(abs(currentX) - abs(mCenterX)).toDouble()val y = abs(abs(mCenterY) - abs(currentY)).toDouble()//半径val trainRadius = sqrt((x.pow(2.0) + y.pow(2.0)))//角度val angle = atan(abs(x) / abs(y)) * 180 / PI//计算后,再根据象限,转换最终的角度var trainAngle = 0fif (trainX <= 0 && trainY >= 0) {trainAngle = (90 - angle + 270).toFloat()} else if (trainX >= 0 && trainY >= 0) {trainAngle = angle.toFloat()} else if (trainX <= 0 && trainY <= 0) {trainAngle = (angle + 180).toFloat()} else if (trainX >= 0 && trainY <= 0) {trainAngle = (90 - angle + 90).toFloat()} else {return}
//        Log.d("dealWithUpEvent", "angle $angle + 转换角度  $trainAngle 半径: $trainRadius")//通过象限,角度,半径,三个条件,确定具体的位置val filterList: MutableList = ArrayList()this.mColorPosInfo.filter {it.startAngle <= trainAngle && it.endAngle >= trainAngle}.filter {it.startRadius >= trainRadius && it.endRadius <= trainRadius}.filter {!it.color.isNullOrBlank()}.toCollection(filterList)if (filterList.size != 1) {return}mListener?.selInfo(LibColorSelInfo().apply {this.colorStr = filterList.first().color})}

至此,全部流程已经说完了,还有不懂的地方,请下载源码了解:

源码
提取码: naf2

that’s all--------------------------------------------------------------

相关内容

热门资讯

走进小城看消费丨江西资溪:低碳...   夏日时节下午4点,江西省抚州市资溪县大觉山景区漂流终点依然热闹。来自南昌的游客余鑫漂流结束后没有...
【中原晨会0625】市场分析专... 来源:市场资讯 (来源:中原证券研究所) 本期重点研报目录 【中原策略】市场分析:电子半导体领涨 ...
南向资金连买4日!低费率+可月... 6月25日早盘,港股红利资产震荡整理。截至11时14分,港股红利低波ETF招商(520550)下跌0...
618成交破百万!紫荆花用一套... 一年一度的618年中大促,是消费市场的晴雨表,也是品牌间最激烈的角力场。当各大品牌在直播间里铆足了劲...
原创 黄... 2026年6月25日的国际金价已经从前期的5500美元高点跌到4200美元下方,累计跌幅超过22%,...
英伟达CEO:Vera Rub... 截至9:38,中证半导体材料设备主题指数(931743)涨2.36%创新高;权重股中,中微公司涨3....
再被催债16亿!“钢铁大王”戴... 澎湃新闻记者 贺梨萍 因“铁本事件”入狱五年的戴国芳重返钢铁行业,但他并没有完成从阶下囚再到“钢铁大...
周三原油价格下跌 随着美国和伊朗在和平谈判中取得进展,越来越多的油轮公开穿越霍尔木兹海峡,原油在战时的价格上涨已经蒸发...
这种蛋白是大脑衰老的开关 这种蛋白是大脑衰老的开关 清晨,假设一位五十岁左右的王女士发现自己常常把手机放在熟悉的抽屉里又找不到...
信通院牵头算力Token出海生... 盘面上,截至11:04,中证科创创业50指数(931643)涨1.68%,创历史新高;权重股中,芯原...
海外 774 亿营收背后:日本... 文 | 游戏价值论 6月23日,彭博社报道了腾讯正在围绕出售多家日本游戏工作室少数股权开展谈判,包...
餐饮“抢人”大战:把店开到公交... 作者 |餐饮老板内参 内参君 医院、公交站、演唱会…餐饮品牌,正在无孔不入 在北京儿童医院,肯德基...
快讯 | 外资扫货!陈翊庭:港... 港交所行政总裁陈翊庭在接受《中国证券报》专访时指出,国际资本对中国资产的看法已彻底扭转,布局中国市场...
2777.77元!A股“股王”... 25日早盘,昨天创下历史新高的A股“股王”联讯仪器,今天上午继续走强,盘中股价再度刷新历史新高。 截...
原创 今... 欧洲自己的媒体直接下结论,欧盟衰退躲不掉,内部分裂拦不住,现在就连欧洲顶尖工业巨头,都偷偷在用中国的...
黄仁勋股东大会放言:本轮AI基... 在当地时间6月24日的英伟达(NVDA.O)2026年度股东大会上,股东批准了该公司全部10名董事会...
国际油价大跌 新华社消息, 纽约原油期货主力合约价格24日盘中跌破每桶70美元,为伊朗战事爆发以来首次。 市场分析...
马云带队插秧,什么信号? 一场别开生面的“务农”,让外界看到了一个不一样的阿里巴巴。 近日,阿里巴巴合伙人、高德董事长刘振飞在...
全球最大产能,最高丰度达99.... 本文转自【科技日报】; 6月23日,高丰度硼-10同位素技术暨产业化成果发布会在山东省东营市举办,全...
黄金大跳水!金饰克价年内暴跌近... 25日,现货黄金盘中震荡,截至发稿,报3985.070美元/盎司,跌0.17%。 当地时间24日,...