热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android自定义View实现颜色选取器

Android 自定义View 颜色选取器,可以实现水平、竖直选择颜色类似 SeekBar 的方式通过滑动选择颜色。 效果图 xml

Android 自定义View 颜色选取器,可以实现水平、竖直选择颜色类似 SeekBar 的方式通过滑动选择颜色。

效果图

xml 属性

1.indicatorColor 指示点颜色
2.indicatorEnable 是否使用指示点
3.orientation 方向
horizontal 水平
vertical 竖直

使用

复制 \library\src…\ColorPickerView.java 和 \library\src\main\res\values\attrs.xml 文件到你的项目中,就可以在使用啦。

示例:

在 xml 中使用:

在 java 中使用:

...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 ColorPickerView picker = (ColorPickerView) findViewById(R.id.colorPickerView);
 picker.setIndicatorColor(Color.GREEN);
 picker.setOrientation(ColorPickerView.Orientation.HORIZONTAL);
 picker.setColors(Color.DKGRAY,Color.RED,Color.WHITE);
 picker.setOnColorPickerChangeListener(new ColorPickerView.OnColorPickerChangeListener() {
  @Override
  public void onColorChanged(ColorPickerView picker, int color) {
  // TODO
  }

  @Override
  public void onStartTrackingTouch(ColorPickerView picker) {
  // TODO

  }

  @Override
  public void onStopTrackingTouch(ColorPickerView picker) {
  // TODO

  }
 });
 }
...

实现解析

1 构成

指示点:类似于 SeekBar 的滑块,通过滑动指示点来选取颜色
颜色条:放置可选颜色

这里写图片描述

颜色条通过 Paint 的 setShader 方法,使用 LinearGradient 渐变色着色器绘制。
指示点只是普通的圆,不过加了阴影,使用 Paint 的 setShadowLayer 方法实现,使用该方法时要关闭硬件加速。

2 实现逻辑

public class ColorPickerView extends View
控件继承自 View。

2.1 onMeasure

onMeasure 方法完成控件大小的测量。控件定义了最小宽高,所以当指定控件宽高,且指定值小于最小宽高,则指定无效。

2.2 onLayout

onLayout 方法比较关键,在该方法中需要完成如下的任务:
1. 计算出控件可用空间
2. 初始化指示点的坐标
3. 计算出颜色条的边界
4. 设置颜色条的颜色(默认的渐变色)
4. 初始化两张 Bitmap(一张用于绘制颜色条,一张用于绘制指示点)

2.2.1 指示点坐标的确定:

初始化时默认使指示点位于控件的中心,而后其位置由 onTouchEvent 方法控制,同时在 onTouchEvent 方法中进行重绘通知以及当前颜色选取。

2.2.2 颜色条边界确定:

颜色条和指示点的大小比例计算方式:我将控件的可用空间(除去上下左右 padding 后剩余的空间)分为 9 份,这 9 份的分配方式是这样的:
假设控件此时为水平方向,且宽度大于高度(这是一般的情况,在控件方向为水平,宽度小于高度时的情况下,边界要进行特殊计算;控件方向为竖直,宽度大于高度的情况也需要特殊处理),取高度作为基数(取宽高中短的一边作为基数)进行平均分配,即: 高度 / 9 = 每一份的大小。

1/9 留白
2/9 指示点在颜色条上方的部分
3/9 颜色条高度
2/9 指示点在颜色条下方的部分
1/9 留白

这样分之后就可以得出 圆的直径占有 9 份中的 7 份,颜色条占有 3 份,两份留白,这是高度的分配情况;颜色条的宽度满足如下条件:在可用宽度的基础上,左右分别留出指示点半径的宽度,这是为了在指示点滑动到左右端点时留出空间给指示点显示,同时保证指示点圆心能完整的扫过整个颜色条。竖直方向的测量计算逻辑也是一样的。

特殊情况:

有两种情况需要特殊处理
1. 控件为水平方向,此时控件的可用宽度小于可用高度。
2. 控件为竖直方向,此时控件的可用宽度大于可用高度。

这两种情况的处理逻辑是一样的,拿第一种情况举例,若此时仍然以短边(此时为宽)作为基数分为 9 份计算,左右分别留出圆半径的宽度,此时圆直径占有了控件可用宽的 7 / 9 ,而且颜色条左右分别留出 3.5 / 9(指示点半径) 的空间,那么颜色条的宽度只剩 9 / 9 - ( 7 / 9) = 2/ 9 ,2 / 9 <7 / 9,而且颜色条和指示点都是居中显示的,这就导致指示点大部分遮挡甚至完全遮挡住颜色条。

解决方法:

针对第一种情况,此时使均分为 9 份的基数为宽(短边)的 1 / 6(控件默认有个最小宽高,默认值的长边与短边之比就是 6 : 1)。
第二种情况下,使基数为高度的 1 / 6。

不足:

假设控件为水平方向,此时控件的可用宽度大于可用高度,但宽与高差值很小。这种情况下,指示点仍然有可能大部分遮挡甚至完全遮挡住颜色条,这种情况下并没有进行处理,此时只能由使用者进行控制。经过测试,在这种情况下(水平方向,宽大于高),当宽高比大于 3 : 1 时,显示效果比较好,所以应该尽量让宽高比大于 3 : 1。竖直方向有同一的问题,不同的是,此时应尽量使高与宽的比值大于 3 : 1.

2.2.3 为什么使用两张 Bitmap

onDraw 方法并不是直接绘制圆角矩形,然后绘制指示点(圆),这样做会使两部分直接绘制在一张位图上,相互覆盖,不利于取得当前指示点所指颜色。因而使用两张位图,一张负责绘制颜色条,一张绘制指示点,onDraw 时分别绘制这两张位图,取色时获取颜色条对应位图上像素点的颜色即可。

取得位图上指定点颜色的方法是使用 Bitmap 的 getPixel(int x,int y) 方法,这个方法可以取得位图上由 x,y 指定的点像素,根据这个像素可以解析出这个点的颜色。

同时这样可以提高控件绘制效率,在大多数情况下颜色条上的可选颜色是不会变化的,此时可以将在可选颜色发生变化后生成的位图直接绘制到控件上,而不需要再一次绘制这个位图,指示点也如此,只需在选取颜色时(滑动指示点时)改变绘制指示点位图的坐标即可,无需再次生成指示点的位图。

2.3 onDraw

onDraw 方法负责绘制,绘制时判断指示点对应位图和颜色条对应位图是否需要重绘,需要则重绘,后绘制两张位图到控件上,否则直接绘制两张位图到控件。

代码中写了很多注释,可以参照注释理解。

已上传 Github,可以在这里找到:DuanJiaNing/ColorPicker

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文基于对相关论文和开源代码的研究,详细介绍了LOAM(激光雷达里程计与建图)的工作原理,并对其关键技术进行了分析。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
author-avatar
可怜的绷带_565
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有