Android自定义控件实现颜色选择器

ColorPickerView 是之前一个智能家居项目实战中所写的自定义控件,主要用于取得RGB 0~255范围的值,然后转换成十六进制0~FF的值,发送给网关控制RGB彩灯。参考的是网上一个朋友的源码写的,多的不说了,先看效果图

activity_mian.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <TextView
 android:id="@+id/tv_info"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_above="@+id/ll_color"
 android:layout_centerHorizontal="true"
 android:layout_marginBottom="20dp"
 android:gravity="center_horizontal"
 android:text="颜色取值" />

 <LinearLayout
 android:id="@+id/ll_color"
 android:layout_width="match_parent"
 android:layout_height="300dp"
 android:layout_centerInParent="true"
 android:gravity="center"
 android:orientation="vertical"></LinearLayout>
</RelativeLayout>

MainActivity.java文件

package zxz.colorpickerdemo;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;

import zxz.colorpickerdemo.view.ColorPickerView;

public class MainActivity extends AppCompatActivity {

 private LinearLayout ll;
 private TextView tv;
 private ColorPickerView colorPickerView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 ll = (LinearLayout) findViewById(R.id.ll_color);
 tv = (TextView) findViewById(R.id.tv_info);

 colorPickerView = new ColorPickerView(this);
 ll.addView(colorPickerView);
 colorPickerView.setOnColorBackListener(new ColorPickerView.OnColorBackListener() {
  @Override
  public void onColorBack(int a, int r, int g, int b) {
  tv.setText("R:" + r + "\nG:" + g + "\nB:" + b + "\n" + colorPickerView.getStrColor());
  tv.setTextColor(Color.argb(a, r, g, b));
  }
 });
 }
}

可以发现,这里自定义控件并没有直接在布局文件使用,原因是因为需要用户根据不同的需求通过自定义控件的构造函数传递给控件,所以通过ViewGroup.add()将ColorPickerView添加进去!

ColorPickerView colorPickerView = new ColorPickerView(context);
 ll.addView(colorPickerView);

-核心部分

就是ColorPickerView的实现代码

package zxz.colorpickerdemo.view;

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.view.MotionEvent;
import android.view.View;

public class ColorPickerView extends View {
 private static final float PI = (float) Math.PI;

 private Paint paintCirclePhantom;
 private Paint paintCircle;
 private Paint paintCenterShadow;
 private Paint paintCenter;
 private Paint paintGrayShadow;
 private Paint paintGray;
 private Paint paintLightShadow;
 private Paint paintLight;
 private double Zoom;
 private int[] arrColorGray;
 private final int[] arrColorCircle = new int[]{0xFFFF0000, 0xFFFF00FF,
  0xFF0000FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000};
 private boolean mRedrawHSV;
 private boolean IsPressCenter;
 private boolean IsMoveCenter;

 private int CenterX = 100;
 private int CenterY = 100;
 private int CenterRadius = 30;
 private String strColor = "";

 private OnColorBackListener l;

 public ColorPickerView(Context context) {
 super(context);
 float density = getContext().getResources().getDisplayMetrics().density;
 double Zoom = (double) (density / 2.0 + 0.5);
 int color = Color.parseColor("#FFFFFF");
 init(color, Zoom);
 }

 public ColorPickerView(Context context, int color, double Zoom) {
 super(context);
 init(color, Zoom);
 }

 private void init(int color, double Zoom) {
 this.Zoom = Zoom;
 CenterX = (int) (100 * Zoom);
 CenterY = (int) (100 * Zoom);
 CenterRadius = (int) (30 * Zoom);
 paintCirclePhantom = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintCenterShadow = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintCenter = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintGrayShadow = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintGray = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintLightShadow = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintLight = new Paint(Paint.ANTI_ALIAS_FLAG);
 paintCirclePhantom.setColor(0xFF000000);
 paintCirclePhantom.setStyle(Paint.Style.STROKE);
 paintCirclePhantom.setStrokeWidth((float) (32 * Zoom));

 paintCircle.setShader(new SweepGradient(0, 0, arrColorCircle, null));
 paintCircle.setStyle(Paint.Style.STROKE);
 paintCircle.setStrokeWidth((float) (32 * Zoom));

 paintCenterShadow.setColor(0xFF000000);
 paintCenterShadow.setStrokeWidth((float) (5 * Zoom));

 paintCenter.setColor(color);
 paintCenter.setStrokeWidth((float) (5 * Zoom));

 paintGrayShadow.setColor(0xFF000000);
 paintGrayShadow.setStrokeWidth((float) (30 * Zoom));

 arrColorGray = new int[]{0xFFFFFFFF, color, 0xFF000000};
 paintGray.setStrokeWidth((float) (30 * Zoom));

 paintLightShadow.setColor(0xFF000000);
 paintLightShadow.setStrokeWidth((float) (60 * Zoom));

 paintLight.setStrokeWidth((float) (60 * Zoom));

 mRedrawHSV = true;
 }

 @Override
 protected void onDraw(Canvas canvas) {
 canvas.translate(CenterX, CenterY);
 float r = CenterX - paintCircle.getStrokeWidth() * 0.5f;
 int color = paintCenter.getColor();
 strColor = "#" + Integer.toHexString(color).substring(2).toUpperCase();

 if (mRedrawHSV) {
  arrColorGray[1] = color;
  paintGray.setShader(new LinearGradient(CenterX, -CenterY, CenterX,
   (float) (100 * Zoom), arrColorGray, null,
   Shader.TileMode.CLAMP));
 }

 canvas.drawOval(new RectF(-r + 3, -r + 3, r + 3, r + 3),
  paintCirclePhantom);
 canvas.drawOval(new RectF(-r, -r, r, r), paintCircle);
 canvas.drawCircle(3, 3, CenterRadius, paintCenterShadow);
 canvas.drawCircle(0, 0, CenterRadius, paintCenter);
 canvas.drawRect(new RectF(CenterX + (float) (18 * Zoom), -CenterY + 3,
   CenterX + (float) (48 * Zoom), (float) (103 * Zoom)),
  paintGrayShadow);
 canvas.drawRect(new RectF(CenterX + (float) (15 * Zoom), -CenterY,
  CenterX + (float) (45 * Zoom), (float) (100 * Zoom)), paintGray); 

 if (IsPressCenter) {
  paintCenter.setStyle(Paint.Style.STROKE);

  if (IsMoveCenter)
  paintCenter.setAlpha(0xFF);
  else
  paintCenter.setAlpha(0x66);

  canvas.drawCircle(0, 0,
   CenterRadius + paintCenter.getStrokeWidth(), paintCenter);
  paintCenter.setStyle(Paint.Style.FILL);
  paintCenter.setColor(color);
 }

 mRedrawHSV = true;
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 setMeasuredDimension(CenterX * 2 + 50, CenterY * 2 + 23);
 }

 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;

 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);
 if (l != null) {
  l.onColorBack(a, r, g, b);
 }
 return Color.argb(a, r, g, b);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 float x = event.getX() - CenterX;
 float y = event.getY() - CenterY;
 boolean inCenter = java.lang.Math.sqrt(x * x + y * y) <= CenterRadius;

 switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN: {
  IsPressCenter = inCenter;
  if (inCenter) {
   IsMoveCenter = true;
   invalidate();
   break;
  }
  }
  case MotionEvent.ACTION_MOVE: {
  if (IsPressCenter) {
   if (IsMoveCenter != inCenter) {
   IsMoveCenter = inCenter;
   invalidate();
   }
  } else if ((x >= -CenterX && x <= CenterX)
   && (y >= -CenterY && y <= CenterY)) {
   float angle = (float) java.lang.Math.atan2(y, x);
   float unit = angle / (2 * PI);
   if (unit < 0)
   unit += 1;
   paintCenter.setColor(interpColor(arrColorCircle, unit));
   invalidate();
  } else {
   int a, r, g, b, c0, c1;
   float p;

   if (y < 0) {
   c0 = arrColorGray[0];
   c1 = arrColorGray[1];
   p = (y + 100) / 100;
   } else {
   c0 = arrColorGray[1];
   c1 = arrColorGray[2];
   p = y / 100;
   }

   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);

   paintCenter.setColor(Color.argb(a, r, g, b));
   mRedrawHSV = false;
   if (l != null) {
   l.onColorBack(a, r, g, b);
   }
   invalidate();
  }
  break;
  }
  case MotionEvent.ACTION_UP: {
  if (IsPressCenter) {
   IsPressCenter = false;
   invalidate();
  }
  break;
  }
 }
 return true;
 }

 public Paint getpaintCirclePhantom() {
 return paintCirclePhantom;
 }

 public void setpaintCirclePhantom(Paint paintCirclePhantom) {
 this.paintCirclePhantom = paintCirclePhantom;
 }

 public Paint getPaintCircle() {
 return paintCircle;
 }

 public void setPaintCircle(Paint paintCircle) {
 this.paintCircle = paintCircle;
 }

 public Paint getPaintCenterShadow() {
 return paintCenterShadow;
 }

 public void setPaintCenterShadow(Paint paintCenterShadow) {
 this.paintCenterShadow = paintCenterShadow;
 }

 public Paint getPaintCenter() {
 return paintCenter;
 }

 public void setPaintCenter(Paint paintCenter) {
 this.paintCenter = paintCenter;
 }

 public Paint getPaintGrayShadow() {
 return paintGrayShadow;
 }

 public void setPaintGrayShadow(Paint paintGrayShadow) {
 this.paintGrayShadow = paintGrayShadow;
 }

 public Paint getPaintGray() {
 return paintGray;
 }

 public void setPaintGray(Paint paintGray) {
 this.paintGray = paintGray;
 }

 public int[] getArrColorGray() {
 return arrColorGray;
 }

 public void setArrColorGray(int[] arrColorGray) {
 this.arrColorGray = arrColorGray;
 }

 public boolean ismRedrawHSV() {
 return mRedrawHSV;
 }

 public void setmRedrawHSV(boolean mRedrawHSV) {
 this.mRedrawHSV = mRedrawHSV;
 }

 public boolean isIsPressCenter() {
 return IsPressCenter;
 }

 public void setIsPressCenter(boolean isPressCenter) {
 IsPressCenter = isPressCenter;
 }

 public boolean isIsMoveCenter() {
 return IsMoveCenter;
 }

 public void setIsMoveCenter(boolean isMoveCenter) {
 IsMoveCenter = isMoveCenter;
 }

 public int[] getArrColorCircle() {
 return arrColorCircle;
 }

 public String getStrColor() {
 return strColor;
 }

 public void setStrColor(String strColor) {
 this.strColor = strColor;
 }

 public double getZoom() {
 return Zoom;
 }

 public void setZoom(double zoom) {
 Zoom = zoom;
 }

 public void setOnColorBackListener(OnColorBackListener l) {
 this.l = l;
 }

 public interface OnColorBackListener {
 public void onColorBack(int a, int r, int g, int b);
 }
}

注意:

1、ColorPickerView重写了两个构造方法,第一个ColorPickerView(context) 这个方法创建的取色器默认绘制的大小比为屏幕密度,默认的颜色为白色;第二个ColorPickerView(context, color, zoom) color为默认颜色,zoom为绘制大小比例。

2、调用colorPickerView的setOnColorBackListener方法监听颜色的变化,回调 a r g b 0~255的值。colorPickerView.getStrColor()获取rgb对应的十六进制值,比如#FF00FF

下载体验一下吧~!

demo下载地址:AndroidStudio工程:ColorPicker !

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

(0)

相关推荐

  • Android自定义控件的步骤

    学习初衷:在工作实际开发过程中,原有的安卓控件已不能满足实际的功能需求,而且有些应用还需要一些独特的展示效果,这时就需要自定义控件来定制控件去满足我们的需求了. 自定义控件的步骤 步骤一:首先要新建一个类CustomView继承自View public class CustomView extends View{} 步骤二:添加构造器,用的是有AttributeSet参数的那个构造方法 public CustomView(Context context,AttributeSet attrs){

  • Android自定义弹窗提醒控件使用详解

    Android中原生的Dialog弹窗提醒控件样式单一,有时候并不能满足我们的项目需求,而且一个工程里面有时候会在多处都用到弹窗提醒的功能,代码会出现大量的冗余,工作之余,就自己实现了这么一个弹窗提醒控件.自定义控件继承自我们的Dialog,样式自定义,弹窗中的文字可通过数组参数初始化,Item个数实现了动态添加,和数组长度一致.对话框底端可展示一个Item(如:确定)或两个Item(如:确定   取消),通过参数设置.废话不多说,直接上代码: 1.自定义对话框的背景样式,在res/values

  • Android自定义日历滑动控件

    本文实例为大家分享了Android自定义日历滑动控件的使用方法,供大家参考,具体内容如下 最近公司项目需要做这个需求,自己才疏学浅,总算能写出个大概来,遂在这里记录下来. 分析 先来分析一下: 首先,我们的需求是可以左右点击查看跳转到下一个月,中间的日历控件可以水平滚动选择日期,所以我们中间的日历控件用一个RecycleView来做,左右两位的为ImageVeiw. LRCalendarView 总体流程: 编写LRCalendarView的布局R.layout.calendar_view 新建

  • Android自定义控件实现按钮滚动选择效果

    本文实例为大家分享了Android实现按钮滚动选择效果的具体代码,供大家参考,具体内容如下 效果图 代码实现 package com.demo.ui.view; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.Handler; import android.support.v4.content.ContextCompat;

  • Android自定义图片轮播Banner控件使用解析

    图片轮播控件,可以说是每个App基本上都会用到的.它可以用来动态的展示多个图片,之前写过两篇博客:实现ViewPager无限循环的方式一和实现ViewPager无限循环的方式二,在这两篇博客中,分析了两种实现ViewPager无限循环的原理,但是在使用的过程中,代码的解偶性很低,所以就使用自定义View的方式,实现无限循环的图片轮播的封装. 先看看效果: 功能特点 支持自定义宽高比例 支持自定义图片切换时间 支持自定义指示点的颜色 支持自定义指示点的背景色 支持自定义指示点的高度 支持是否显示指

  • Android自定义控件实现不规则区域点击事件

    本文实例为大家分享了Android实现不规则区域点击事件的具体代码,供大家参考,具体内容如下 先看看效果 对于上面的图形实现主要用到svg,通过解析svg获取不规则的图形,对于svg文件这个一般需要美工提供,不需要我们开发实现. 实现上面效果第一步是解析svg文件代码如下 package demo.zjd.com.taiwandemo.utils; import android.graphics.RectF; import android.util.Xml; import org.xmlpull

  • Android自定义控件实现带文字提示的SeekBar

    1.写在前面 SeekBar控件在开发中还是比较常见的,比如音视频进度.音量调节等,但是原生控件有时还不能满足我们的需求,今天就来学习一下如何自定义SeekBar控件,本文主要实现了一个带文字指示器效果的SeekBar控件 看下最终效果: IndicatorSeekBar 2.实现 IndicatorSeekBar public class IndicatorSeekBar extends AppCompatSeekBar { // 画笔 private Paint mPaint; // 进度文

  • Android自定义动画根据控件Y轴旋转动画(仿红包)

    这里给正在学安卓的小白们分享一个动画吧,用处挺多,代码也不多,还望各位大佬不要打击. 进入正题,先看看效果 效果很炫酷很美好 好了 来看代码吧    该说的都在代码注释里面  这个不用多说 代码极其简单 //自定义一个类继承Animation(android.view.animation.Animation)抽象类 public class MyAnimation extends Animation { // 先定义成员变量 //X轴的中心坐标 int center_X; //Y轴的中心坐标 i

  • Android组合式自定义控件实现购物车加减商品操作

    本文实例为大家分享了Android实现购物车加减商品操作的具体代码,供大家参考,具体内容如下 MainActivity.java public class MainActivity extends AppCompatActivity { private Addand mAddand; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setConte

  • Android自定义控件ListView下拉刷新的代码

    ListView在实际实用中,一般都会有下新刷新和上拉加载的动态效果,今天要学的就是如何自定义带下拉刷新的ListView. 原理解析:一般将有下拉刷新的listview分成四种不同的状态来进行不同的显示效果. 1.完成状态done:listview正常显示状态 2.下拉状态pull:listview正在下拉时的状态 3.释放状态release:listview下拉后松开的状态 4.更新状态refreshing:listview下拉后加载数据时的状态 实现步骤: 自定义CustomListVie

随机推荐