Android 仿PhotoShop调色板应用(三) 主体界面绘制

2024-03-10 02:48

本文主要是介绍Android 仿PhotoShop调色板应用(三) 主体界面绘制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android 仿PhotoShop调色板应用(三) 主体界面绘制

   关于PhotoShop调色板应用的实现我总结了两个最核心的部分:

  1. 主体界面不同区域的绘制

  2. 颜色选择的生成与交互

 这里我讲述一下第一要点,也就是ColorPickerDialog对主体界面的绘制.

   首先还是看一下ColorPickerDialog整体显示的效果(见图1)

                                          图1


对应着效果图我画了一张界面结构分析图,相信看了之后会对该界面的组成很快能够掌握:(见图2)

  图2

一. 界面组成

   可以看到整个显示的部分即为ColorPickerDialog. 这个Dialog根据组件的构成及功能实现上可以分为两大部分:

  1. 红色边框区域 ColorPickerView绘制而成. 主要作为颜色区域的选择,此区域又划分为三个部分:

      (1)  Saturation Area 饱和度选择区域

      (2)  Hue Area 色相选择区域

      (3)  Alpha Area 透明度选择区域  绘制此区域借助了上一篇讲到的AlphaPatternDrawable类

2. 蓝色边框区域 由ColorPickerPanelView绘制. 左边的部分作为初始颜色显示 右边的部分做颜色选择的实时显示区域,点击后可将颜色设置为默认值


该Dialog的布局文件dialog_color_picker.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"android:paddingLeft="5dp"android:paddingRight="5dp" ><net.margaritov.preference.colorpicker.ColorPickerViewandroid:id="@+id/color_picker_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layerType="software"android:tag="portrait" /><LinearLayoutandroid:id="@+id/text_hex_wrapper"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginLeft="6dp"android:layout_marginRight="6dp" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="left"android:text="@string/press_color_to_apply"android:textAppearance="?android:attr/textAppearanceSmall" /><EditTextandroid:id="@+id/hex_val"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:hint="HEX"android:imeOptions="actionDone"android:maxLength="7"android:singleLine="true"android:inputType="textCapCharacters"android:visibility="gone" ></EditText></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="40dp"android:layout_marginBottom="10dp"android:orientation="horizontal" ><net.margaritov.preference.colorpicker.ColorPickerPanelViewandroid:id="@+id/old_color_panel"android:layout_width="0px"android:layout_height="fill_parent"android:layout_weight="0.5" /><TextViewandroid:layout_width="wrap_content"android:layout_height="fill_parent"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:gravity="center"android:text="→"android:textSize="20sp" /><net.margaritov.preference.colorpicker.ColorPickerPanelViewandroid:id="@+id/new_color_panel"android:layout_width="0px"android:layout_height="wrap_content"android:layout_weight="0.5" /></LinearLayout></LinearLayout>


二. 不同区域的绘制实现:

  1.     Saturation Area 饱和度选择区域

这里用到了组合渲染(ComposeShader)的方式.

 (1)使用了两个线性渲染器:一个作为亮度的显示渲染,一个作为饱和度的显示渲染,    因为我们可以看到颜色渐变和亮度渐变的综合显示效果

      此区域完成了HSV(也叫HSB)色彩空间之Saturation(饱和度)value(色调)/brightness(明度)的综合显示

(2) 选择圆环绘制:  分为了内外两个圆环分别绘制. 黑色内圆及灰色外圆

      具体实现请看以下代码


/*** 绘制饱和度选择区域* @param canvas*/private void drawSatValPanel(Canvas canvas){final RectF	rect = mSatValRect;if(BORDER_WIDTH_PX > 0){mBorderPaint.setColor(mBorderColor);canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);}//明度线性渲染器if (mValShader == null) {mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,0xffffffff, 0xff000000, TileMode.CLAMP);}//HSV转化为RGBint rgb = Color.HSVToColor(new float[]{mHue,1f,1f});//饱和线性渲染器mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,0xffffffff, rgb, TileMode.CLAMP);//组合渲染 = 明度线性渲染器 + 饱和线性渲染器ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);mSatValPaint.setShader(mShader);canvas.drawRect(rect, mSatValPaint);//初始化选择圆块的位置Point p = satValToPoint(mSat, mVal);//绘制黑色内圆mSatValTrackerPaint.setColor(0xff000000);canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);//绘制外圆mSatValTrackerPaint.setColor(0xffdddddd);canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);}

2.Hue Area 色相选择区域

   (1) 颜色渲染部分仍为竖直方向的线性渐变.这里可以看一下对应颜色数组的生成:

private int[] buildHueColorArray(){int[] hue = new int[361];int count = 0;for(int i = hue.length -1; i >= 0; i--, count++){hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});}return hue;}

这里使用了一个大小为 361的int数组, 根据当前位置生成不同的 hsv颜色数组

通过Color.HSVToColor,将HSV转换为ARGB的形式,因为在线性渐变渲染中,我们不能直接使用HSV色彩,而是需要使用ARGB制式的颜色.

因此我们看到了一个数值方向的一个多彩变换效果       

(2) 绘制矩形颜色选择条区域


/*** 绘制右侧色相选择区域* @param canvas*/private void drawHuePanel(Canvas canvas){final RectF rect = mHueRect;if(BORDER_WIDTH_PX > 0){mBorderPaint.setColor(mBorderColor);canvas.drawRect(rect.left - BORDER_WIDTH_PX,rect.top - BORDER_WIDTH_PX,rect.right + BORDER_WIDTH_PX,rect.bottom + BORDER_WIDTH_PX,mBorderPaint);}//初始化色相线性渲染器if (mHueShader == null) {mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom, buildHueColorArray(), null, TileMode.CLAMP);mHuePaint.setShader(mHueShader);}canvas.drawRect(rect, mHuePaint);float rectHeight = 4 * mDensity / 2;//初始化色相选择器选择条位置Point p = hueToPoint(mHue);RectF r = new RectF();r.left = rect.left - RECTANGLE_TRACKER_OFFSET;r.right = rect.right + RECTANGLE_TRACKER_OFFSET;r.top = p.y - rectHeight;r.bottom = p.y + rectHeight;//绘制选择条canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);}

3. Alpha Area 透明度选择区域

  这里主要借助于AlphaPatternDrawable进行绘制,见上一篇博客:

Android 仿PhotoShop调色板应用(二) 透明度绘制之AlphaPatternDrawable

具体请见注释,渲染部分和Hue Area类似

/*** 绘制底部透明度选择区域* @param canvas*/private void drawAlphaPanel(Canvas canvas){if(!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;final RectF rect = mAlphaRect;if(BORDER_WIDTH_PX > 0){mBorderPaint.setColor(mBorderColor);canvas.drawRect(rect.left - BORDER_WIDTH_PX,rect.top - BORDER_WIDTH_PX,rect.right + BORDER_WIDTH_PX,rect.bottom + BORDER_WIDTH_PX,mBorderPaint);}mAlphaPattern.draw(canvas);float[] hsv = new float[]{mHue,mSat,mVal};//hsv数组int color = Color.HSVToColor(hsv);int acolor = Color.HSVToColor(0, hsv);//初始化透明度线性渲染器mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,color, acolor, TileMode.CLAMP);mAlphaPaint.setShader(mAlphaShader);canvas.drawRect(rect, mAlphaPaint);if(mAlphaSliderText != null && mAlphaSliderText!= ""){canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity, mAlphaTextPaint);}float rectWidth = 4 * mDensity / 2;//初始化透明度选择器选择条位置Point p = alphaToPoint(mAlpha);RectF r = new RectF();r.left = p.x - rectWidth;r.right = p.x + rectWidth;r.top = rect.top - RECTANGLE_TRACKER_OFFSET;r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);}


4. ColorPickerPanelView

    由于此区域可做最终颜色的显示,所以也借助了AlphaPatternDrawable的实现

    此矩形区域绘制相对比较简单:

	final RectF	rect = mColorRect;if(BORDER_WIDTH_PX > 0){mBorderPaint.setColor(mBorderColor);canvas.drawRect(mDrawingRect, mBorderPaint);}if(mAlphaPattern != null){mAlphaPattern.draw(canvas);}mColorPaint.setColor(mColor);canvas.drawRect(rect, mColorPaint);

至此,ColorPickerDialog主体面板绘制部分已讲述完毕.下面我会讲述另一大核心部分:颜色选择生成的交互.

如果对颜色渲染方面还是不太清楚的话,可以参照我之前写的颜色渲染系列,关于原理和具体API的讲解.

这篇关于Android 仿PhotoShop调色板应用(三) 主体界面绘制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/792778

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

5分钟获取deepseek api并搭建简易问答应用

《5分钟获取deepseekapi并搭建简易问答应用》本文主要介绍了5分钟获取deepseekapi并搭建简易问答应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1、获取api2、获取base_url和chat_model3、配置模型参数方法一:终端中临时将加

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Python调用另一个py文件并传递参数常见的方法及其应用场景

《Python调用另一个py文件并传递参数常见的方法及其应用场景》:本文主要介绍在Python中调用另一个py文件并传递参数的几种常见方法,包括使用import语句、exec函数、subproce... 目录前言1. 使用import语句1.1 基本用法1.2 导入特定函数1.3 处理文件路径2. 使用ex

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Python中的可视化设计与UI界面实现

《Python中的可视化设计与UI界面实现》本文介绍了如何使用Python创建用户界面(UI),包括使用Tkinter、PyQt、Kivy等库进行基本窗口、动态图表和动画效果的实现,通过示例代码,展示... 目录从像素到界面:python带你玩转UI设计示例:使用Tkinter创建一个简单的窗口绘图魔法:用

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3