搜档网
当前位置:搜档网 › Android进阶——自定义View之自己绘制彩虹圆环调色板

Android进阶——自定义View之自己绘制彩虹圆环调色板

Android进阶——自定义View之自己绘制彩虹圆环调色板
Android进阶——自定义View之自己绘制彩虹圆环调色板

Android进阶——自定义View之自己绘

制彩虹圆环调色板

引言

前面几篇文章都是关于通过继承系统View和组合现有View来实现自定义View的,刚好由于项目需要实现一个滑动切换LED彩灯颜色的功能,所以需要一个类似调色板的功能,随着手在调色板有效区域滑动,LED彩灯随即显示相应的颜色,也可以通过左右的按钮,按顺序切换显示一组颜色,同时都随着亮度的改变LED彩灯的亮度随即变化,这篇基本上把继承View重绘实现自定义控件的大部分知识总结了下(当然还有蛮多没有涉及到,比如说自适应布局等),源码在Github上

一、继承View绘制自定义控件的通用步骤

自定义属性和继承View重写onDraw方法

实现构造方法,其中public RainbowPalette(Context context, AttributeSet attrs) 必须实现,否则无法通过xml引用,public RainbowPalette(Context context) ,public RainbowPalette(Context context, AttributeSet attrs, int defStyleAttr)可选,通常在构造方法中完成属性和其他成员变量的初始化

重写onMeasure方法,否则在xml中有些设置布局参数无效

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(width, height);//重新设置View的位置,若不重写的话,则不会布局,即使设置centerInParent为true也无效

//setMeasuredDimension(width,height);

}

手动调用invalidate或者postInvalidateon方法完成界面刷新

重写onTouchEvent方法实现基本的交互

定义回调接口供外部调用

二、彩虹圆环调色板设计思想

1、UI构成

首先从整个形状来看是个圆环,系统自有的控件明显没具有这个功能,只能是继承View重写OnDraw来完成绘制工作。前面Android入门——利用Canvas完成绘制点、圆、直线、路径、椭圆、多边形等2D图形可以知道通过Paint可以在Canvas绘制任何图形,包括圆环,于是整体的结构就出来了,中心实体小圆作为指示当前颜色的标记,外圈渐变色圆环作为调色板的取色区域(可以通过给Paint传入Shader shader = new SweepGradient(0, 0, gradientColors, null)来绘制渐变色),最外圈的光环可以绘制多个圆环,而作为指示器标记的小圆点(也可以传入图片资源)也是一个圆形,如此一来UI方面的结构基本明了。

2、交互设计

一般来说自定义View的人机交互都是通过回调的方式的来实现的。

滑动选择颜色:自定义控件的滑动自然是重写onTouchEvent,然后调用invalidate手动触发View重绘(即重新调用onDraw)

颜色指示器的显示的位置:手动触发invalidate重新调用onDraw绘制

中心圆形自动同步选中的颜色:手动触发invalidate重新调用onDraw绘制

仅在圆环处滑动选择颜色:如果面积小于外圆大于内圆的就认为是有效滑动

/**

* 是否是有效Touch即是否是按在圆环之上的

* @return

*/

private boolean isEfectiveTouch(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;

}

}

三、实现彩虹圆环调色板

1、自定义属性

attr.xml

2、重写View

import com.xiaoi.app.zkSmartHome.R;

/**

* auther: Crazy.Mo

* Date: 2016/12/13

* Time:10:27

* Des:自定义的调色板,可以绘制圆形指示器,也可以自定义图标指示器,但是指示器会超出边界

*/

public class RainbowPalette extends View {

private Context context;

private Paint borderPaint;//色环外圈的彩虹圆环

private Paint palettePaint;//渐变色环的画笔

private Paint centerPaint;//中间圆画笔,用于显示当前选中的颜色

private Paint indictorPaint; // 可移动小球画笔

private int indictorColor;

private int[] gradientColors;//渐变色环颜色

private int centerCircleColor;

private int width;//当前调色板的宽度

private int height;//当前调色板的高度

private float paletteRadius;//色环半径,整个环形外径,直接决定这个调色板的整体的大小,画渐变环可以看成画一个完整的圆形再挖掉一个小圆

private float centerRadius;//中心圆半径

private float paletteWidth;//色环的宽度

private float indictorRadius;//小球的半径

private Point indictorPosition;// 小球当前位置

private Point centerPosition;//圆心的位置,色环圆心的位置

private Bitmap indicatorBitmap; // 指示器小球的图标

private int indictorResId;//指示器图标的id

private RainbowPalette.OnColorChangedListen listen;

private static boolean isShowIndictor=true;

private final static int BORDER_WIDTH=2;

private final static int PALETTE_WIDTH=100;

private final static int CENTER_CIRCLE_WIDTH=5;

private final static int INDICTOR_WIDTH=5;

private final static int DEF_INDICTOR_COLOR=0xFFc9f5f1;//设置指示小圆形的颜色private final static int DEF_CIRCLE_COLOR=0xFF0511FB;//设置中间圆的默认颜色

public RainbowPalette(Context context) {

super(context);

}

public RainbowPalette(Context context, AttributeSet attrs) {

super(context, attrs);

this.context = context;

init(attrs);

}

public RainbowPalette(Context context, AttributeSet attrs, int defStyleAttr){

super(context, attrs, defStyleAttr);

this.context=context;

init(attrs);

}

private void init(AttributeSet attrs){

setPaletteSize();

initAttrColor(attrs);

initPaint();

initPosition();

initRadiusWidth(attrs);

}

/**

* 用于设置中间圆的颜色

* @param color

*/

public void setCenterPaint(int color){

centerPaint.setColor(color);

}

/**

* 设置调色板的尺寸

*/

private void setPaletteSize(){

WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//获取WM对象

int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);//获取屏幕的高度*0.5

int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);//获取屏幕宽度的0.7

this.height = height - 36;

this.width = width;

setMinimumHeight(height - 36);

setMinimumWidth(width);

}

/**

* 设置颜色指示器的位置

* @param point

*/

public void setIndictorPosition(Point point){

if(point!=null) {

this.indictorPosition.x = point.x;

this.indictorPosition.y = point.y;

}

}

/**

* 设置是否显示颜色指示器

* @param isShow

*/

public static void setIndictorShow(boolean isShow){

RainbowPalette.isShowIndictor=isShow;

}

/**

* 设置指示器小球Color的默认值

* @param color

*/

public void setBallColor(int color){

this.indictorColor=color;

}

/**

* 初始化各种Paint对象

*/

private void initPaint(){

setGradientColors();

Shader shader = new SweepGradient(0, 0, gradientColors, null);//SweepGradient渐变

//外层彩虹光环

borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿。给Paint加上抗锯齿标志

borderPaint.setAntiAlias(true);

borderPaint.setShader(shader);//传入着色器

borderPaint.setStyle(Paint.Style.STROKE);//设置仅描边

borderPaint.setStrokeWidth(BORDER_WIDTH);//设置描边的宽度,直接对应

//初始化色环的Paint对象

palettePaint = new Paint(Paint.ANTI_ALIAS_FLAG);//在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿。给Paint加上抗锯齿标志

palettePaint.setAntiAlias(true);

palettePaint.setShader(shader);//传入着色器

palettePaint.setStyle(Paint.Style.STROKE);//设置仅描边

palettePaint.setStrokeWidth(PALETTE_WIDTH);//设置描边的宽度,直接对应

//初始化中心圆的Paint对象

centerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

centerPaint.setAntiAlias(true);

centerPaint.setColor(centerCircleColor);

centerPaint.setStrokeWidth(CENTER_CIRCLE_WIDTH);

//初始化小球对象

indictorPosition=new Point();

indictorPaint= new Paint(Paint.ANTI_ALIAS_FLAG);

indictorPaint.setAntiAlias(true);

indictorPaint.setColor(indictorColor);

indictorPaint.setStrokeWidth(INDICTOR_WIDTH);

}

private void initAttrColor(AttributeSet attrs){

TypedArray types = context.obtainStyledAttributes(attrs,

R.styleable.rainbow_palette);

try {

centerCircleColor = types.getColor( R.styleable.rainbow_palette_center_circle_defcolor,DEF_CIRCLE_COLOR );

indictorColor = types.getColor( R.styleable.rainbow_palette_indicator_color,DEF_INDICTOR_COLOR );

} finally {

types.recycle(); // TypeArray用完需要recycle

}

}

/**

* 设置色环和中心圆、圆形指示小球的半径,宽度

*/

private void initRadiusWidth(AttributeSet attrs){

TypedArray types = context.obtainStyledAttributes(attrs,

R.styleable.rainbow_palette);

try {

paletteWidth = types.getDimensionPixelOffset( R.styleable.rainbow_palette_palette_width, PALETTE_WIDTH);

paletteRadius=types.getDimensionPixelOffset(R.styleable.rainbow_palette_palette_radius,(int)(wi dth / 2 - palettePaint.getStrokeWidth()*1.2f));

centerRadius=types.getDimensionPixelOffset(R.styleable.rainbow_palette_palette_radius,(int)((pa letteRadius - palettePaint.getStrokeWidth() / 2 ) * 0.5f));

indictorResId=types.getResourceId(R.styleable.rainbow_palette_ic_indicator,0);

if(indictorResId==0) {

//未指定指示器的图标采用默认的绘制一个小圆形

indictorRadius = (float) (centerRadius * 0.5);

}else {

initIndictorImg();//使用设置的指示器目标

}

} finally {

types.recycle(); // TypeArray用完需要recycle

}

}

/**

* 初始化颜色指示器,设置指定图片

*/

private void initIndictorImg(){

// 将背景图片大小设置为属性设置的直径

indicatorBitmap = BitmapFactory.decodeResource(getResources(), indictorResId );

//indicatorBitmap = Bitmap.createScaledBitmap(indicatorBitmap, (int)centerRadius,(int)centerRadius, false);

indicatorBitmap=

Bitmap.createScaledBitmap(indicatorBitmap,indicatorBitmap.getWidth(),indicatorBitmap.getHeig ht(),true);

indictorRadius=indicatorBitmap.getHeight();

}

/**

* 设置色环的绘制圆心

*/

private void initPosition(){

centerPosition=new Point();

centerPosition.set(width/2,height/2-50);

indictorPosition.set(0,0);

}

/**

* 设置渐变环的颜色取值

*/

public void setGradientColors(){

gradientColors = new int[] {0xFFFF0000, 0xFFFF00FF, 0xFF0000FF,0xFF00FFFF, 0xFF00FF00,0xFFFFFF00, 0xFFFF0000};

}

private void drawBorder(Canvas canvas){

borderPaint.setAlpha(220);

canvas.drawOval(new RectF(-(paletteRadius+55), -(paletteRadius+55), (paletteRadius+55), (paletteRadius+55)), borderPaint);//画次外圈

borderPaint.setAlpha(100);

canvas.drawOval(new RectF(-(paletteRadius+60), -(paletteRadius+60), (paletteRadius+60), (paletteRadius+60)), borderPaint);//画外圈

borderPaint.setAlpha(60);

canvas.drawOval(new RectF(-(paletteRadius+65), -(paletteRadius+65), (paletteRadius+65), (paletteRadius+65)), borderPaint);//画外圈

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.translate(centerPosition.x,centerPosition.y);//移动中心,要不然会导致画出来之后不能完全显示,此时圆心相当于是由(0,0)变为(width / 2, height / 2 - 50)

canvas.drawCircle(0,0, centerRadius, centerPaint);//画中心圆

canvas.drawOval(new RectF(-paletteRadius, -paletteRadius, paletteRadius, paletteRadius), palettePaint);//画色环

drawBorder(canvas);

if(isShowIndictor) {

if (indictorResId == 0) {

canvas.drawCircle(indictorPosition.x, indictorPosition.y, (float) (centerRadius * 0.5), indictorPaint);//画颜色指示器小球

} else {

canvas.drawBitmap(indicatorBitmap, indictorPosition.x, indictorPosition.y, indictorPaint);//画指示器指定图片

}

}

Log.e("Position", "indictorPosition: X:"+indictorPosition.x+"Y:"+indictorPosition.y );

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(width, height);//重新设置View的位置,若不重写的话,则不会布局,即使设置centerInParent为true也无效

//setMeasuredDimension(width,height);

}

// 可以实现点击的时候显示对应的指示点,但会超过边界

@Override

public boolean onTouchEvent(MotionEvent event) {

float x = event.getX() - width / 2;//event.getX()以父视图的左上角作为原点

float y = event.getY() - height / 2 + 50;

boolean isEcfect = isEfectiveTouch(x, y,

paletteRadius + palettePaint.getStrokeWidth() / 2, paletteRadius - palettePaint.getStrokeWidth() / 2);

int choosedColor;

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

if(isEcfect){

float angle = (float) Math.atan2(y, x);

float unit = (float) (angle / (2 * Math.PI));

if (unit < 0) {

unit += 1;

}

choosedColor=getColorByTouchPalette(gradientColors,unit);

indictorPosition.set((int) (event.getX()-(width / 2)), (int) (event.getY()-(width / 2)));

centerPaint.setColor(choosedColor);

if(listen!=null) {

listen.onColorChange(choosedColor);

}

}

else {

return false;

}

break;

case MotionEvent.ACTION_MOVE:

if(isEcfect){

float angle = (float) Math.atan2(y, x);

float unit = (float) (angle / (2 * Math.PI));

if (unit < 0) {

unit += 1;

}

choosedColor=getColorByTouchPalette(gradientColors,unit);

indictorPosition.set((int) (event.getX()-(width / 2)), (int) (event.getY()-(width / 2)));

centerPaint.setColor(choosedColor);

invalidate();

}

break;

case MotionEvent.ACTION_UP:

if(isEcfect){

float angle = (float) Math.atan2(y, x);

float unit = (float) (angle / (2 * Math.PI));

if (unit < 0) {

unit += 1;

}

choosedColor=getColorByTouchPalette(gradientColors,unit);

indictorPosition.set((int) (event.getX()-(width / 2)), (int) (event.getY()-(width / 2)));

centerPaint.setColor(choosedColor);

if(listen!=null) {

listen.onColorChange(choosedColor);

listen.onColorChangeUp((int) (event.getX()-(width / 2)), (int) (event.getY()-(width / 2)));

}

}

return true;

default:

break;

}

if (isEcfect) {

invalidate();

}

return true;

}

/**

* 获取圆环上颜色

* @param colors

* @param unit

* @return

*/

private int getColorByTouchPalette(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);

}

private int ave(int s, int d, float p) {

return s + Math.round(p * (d - s));

}

/**

* 是否是有效Touch即是否是按在圆环之上的

* @return

*/

private boolean isEfectiveTouch(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;

}

}

/**

* @describe 勾股定理求触摸点与圆心之间直线与水平方向的夹角角度

* @param a 触摸点

* @param b 圆心

* @return

*/

public float getRadian(Point a, Point b) {

float lenA = Math.abs(b.x - a.x);

float lenB = Math.abs(b.y - a.y);

float lenC = (float) Math.sqrt(lenA * lenA + lenB * lenB);

float ang = (float) Math.acos(lenA / lenC);

ang = ang * (b.y < a.y ? -1 : 1);

return ang;

}

/**

* 设置小球的绘制位置,只能绘制在色环内

* @return

*/

private Point setIndictorPositionBorder(int x, int y){

Point touchPosition=new Point(x,y);

Point centerCircle=new Point(0,0);

float radian=getRadian(touchPosition,centerCircle);

float distance=getTwoPointDistance(centerCircle,touchPosition);//touch点和圆心之间的距离

float touchToBallDistance;//touch点和内切时小球圆心所在的位置之间的距离,如果不超出色环之外,这两点位置重合,如果超出了则自动移到内切位置处

if(distance+indictorRadius>(int)paletteRadius){

touchToBallDistance= Math.abs(distance-paletteRadius+indictorRadius);//touch点和内切(与外环)时小球圆心所在的位置之间的距离

if(Math.abs(Math.cos(radian))==1){//如果夹角为0或者180°

if(x<0){

indictorPosition.set(-(int)(paletteRadius-20),0);

}else {

indictorPosition.set((int)(paletteRadius-20),0);

}

}

indictorPosition.set((int)(x-(Math.cos(radian)*touchToBallDistance)),(int)(y-(Math.sin(radian)*to uchToBallDistance)));

}else if(distance<((int)paletteRadius-160)){

touchToBallDistance=

Math.abs(paletteRadius-160-distance+indictorRadius);//touch点和外切(与内环)时小球圆心所在的位置之间的距离

indictorPosition.set((int)(x+(Math.cos(radian)*touchToBallDistance)),(int)(y+(Math.sin(radian)*t ouchToBallDistance)));

}else {

indictorPosition.set(x,y);

}

return indictorPosition;

}

/**

* 求两点之间的距离

* @param a

* @param b

* @return

*/

public float getTwoPointDistance(Point a, Point b){

return (float) Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));

}

public void setOnChangeListen(OnColorChangedListen listen){

this.listen=listen;

}

public interface OnColorChangedListen{

void onColorChange(int color);//自定义的颜色切换的时候触发的回调

void onColorChangeUp(int x,int y);

}

}

四、应用彩虹圆环调色板

MainActivity.Java

public class MainActivity extends AppCompatActivity implements RainbowPalette.OnColorChangedListen ,View.OnClickListener,SeekBar.OnSeekBarChangeListen er{

private RainbowPalette rainbowPalette;

private TextView txtTitle,txtChoosePre,txtChooseNext;

private SeekBar seekBar;

private SparseArray sparseArray;

private int currentIndex = 6;//当前的颜色的index,默认为蓝色

private int currentColor;//选中的颜色

private String currentRGB;

private int[] ledNormalColor = {0xFFFFFFFF, 0xFFFF0000, 0xFFF3990C, 0xFFEEF60B, 0xFF3C981B, 0xFF3CE2F3, 0xFF0511FB, 0xFFAB56EE};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(https://www.sodocs.net/doc/3f18806220.html,yout.activity_main);

init();

}

private void initViews(){

rainbowPalette= (RainbowPalette) findViewById(R.id.imv_led_palettle);

txtTitle= (TextView) findViewById(R.id.id_txt_palette);

txtChoosePre= (TextView) findViewById(https://www.sodocs.net/doc/3f18806220.html,_choose_pre);

txtChooseNext= (TextView) findViewById(https://www.sodocs.net/doc/3f18806220.html,_choose_next);

seekBar= (SeekBar) findViewById(R.id.id_alpha_seek_bar);

txtChoosePre.setOnClickListener(this);

txtChooseNext.setOnClickListener(this);

rainbowPalette.setOnChangeListen(this);

seekBar.setOnSeekBarChangeListener(this);

}

private void init(){

initViews();

initColorPosition();

}

/**

* 手动设置指示小球显示的位置

*/

public void setIndictorPosition(int index){

if (sparseArray!=null) {

rainbowPalette.setIndictorPosition((Point)

sparseArray.get(ledNormalColor[index]));

rainbowPalette.setCenterPaint((ledNormalColor[currentIndex]));

}

RainbowPalette.isNeedShowIndictor=false;

rainbowPalette.invalidate();

}

private void onChooseColor(View view){

switch (view.getId()){

case https://www.sodocs.net/doc/3f18806220.html,_choose_pre:

setIndictorPosition(choosePreColor());

break;

case https://www.sodocs.net/doc/3f18806220.html,_choose_next:

setIndictorPosition(chooseNextColor());

break;

default:

break;

}

}

/**

* 选择前一种颜色,并返回对应的索引

*

* @return

*/

private int choosePreColor() {

int size = ledNormalColor.length;

if (currentIndex == 0) {

currentIndex = size;

}

currentIndex = currentIndex - 1;

currentColor = ledNormalColor[currentIndex];

return currentIndex;

}

/**

* 选择后一种颜色,并返回对应的索引

*

* @return

*/

private int chooseNextColor() {

int size = ledNormalColor.length;

if (currentIndex == size - 1) {

currentIndex = -1;

}

currentIndex = currentIndex + 1;

currentColor = ledNormalColor[currentIndex];

return currentIndex;

}

/**

* 初始化固定颜色对应的坐标值

*/

private void initColorPosition(){

Point[] points={new Point(-75,1),new Point(110,-2),new Point(102,-88),new Point(57,-120),

new Point(-69,-131),new Point(-145,-18),new Point(-64,102),new Point(44,103)} ;

sparseArray = new SparseArray();

for(int i=0;i

sparseArray.append(ledNormalColor[i],points[i] );

}

}

/**

* 获取argb模式的颜色值并转为字符串

* @param color

* @return

*/

private String parseArgb(int color){

int a = (color >>> 24);

int r = (color >> 16) & 0xFF;

int g = (color >> 8) & 0xFF;

int b = (color) & 0xFF;

return String.valueOf(a)+String.valueOf(r)+String.valueOf(g)+String.valueOf(b);

}

private String parseRGB(int color){

int r = (color >> 16) & 0xFF;

int g = (color >> 8) & 0xFF;

int b = (color) & 0xFF;

return String.valueOf(r)+String.valueOf(g)+String.valueOf(b);

}

@Override

public void onColorChange(int color) {

txtTitle.setTextColor(color);

currentColor=color;

currentRGB=Integer.toHexString(color);

Log.e("Color", "onColorChange: "+ Color.red(color)+Color.green(color)+Color.blue(color));

Log.e("Color", "onColorChange:parseArgb "+parseArgb(color) );

Log.e("Color", "onColorChange:parseRGB "+parseRGB(color) );

Log.e("Color", "onColorChange: "+Integer.toHexString(color) );//获取十进制字符串表示argb模式的颜色0xFFF3990C-->fff3990c

}

/**

* 获取最终的颜色值ARGB模式的

* @param progress

* @return

*/

private int getChangedColor(int progress){

String red,green,blue;

if(https://www.sodocs.net/doc/3f18806220.html,ress==0){

progress=1;

}

if(currentRGB==null){

currentRGB="FF0511FB";

}

red=currentRGB.substring(2,4);

green=currentRGB.substring(4,6);

blue=currentRGB.substring(6);

return

Color.argb(progress,Integer.parseInt(red,16),Integer.parseInt(green,16),Integer.parseInt(blue,16));

}

@Override

public void onClick(View v) {

onChooseColor(v);

}

@Override

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

currentColor = getChangedColor(progress);

rainbowPalette.setCenterPaint(currentColor);

Log.e("Color", "onProgressChanged: "+Integer.toHexString(currentColor) );

rainbowPalette.invalidate();

txtTitle.setTextColor(currentColor);

Log.e("Color", "onProgressChanged: rgb"+ Color.red(currentColor)+Color.green(currentColor)+Color.blue(currentColor));

}

@Override

public void onStartTrackingTouch(SeekBar seekBar) {

return;

}

@Override

public void onStopTrackingTouch(SeekBar seekBar) {

return;

}

}

activity_main.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/colorBcg">

android:id="@+id/id_txt_palette"

android:textSize="22sp"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="自定义的调色板CrazyMo"/>

android:id="@+id/rl_led_paletle"

android:layout_below="@id/id_txt_palette"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="86dp"

android:gravity="https://www.sodocs.net/doc/3f18806220.html,nter"

android:layout_alignParentTop="true"

>

android:id="@+id/tv_choose_pre"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_centerInParent="true"

android:layout_marginLeft="24dp"

android:layout_marginRight="24dp"

android:background="@mipmap/bcg_pre_btn"

android:clickable="https://www.sodocs.net/doc/3f18806220.html,ue"/>

android:id="@+id/tv_choose_next"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_centerInParent="true"

android:layout_marginRight="24dp"

android:layout_marginLeft="24dp"

android:background="@mipmap/bcg_next_btn"

android:clickable="true"/>

crazymo:ic_indicator="@mipmap/src_indicator"

crazymo:center_circle_defcolor="#0511FB"

android:id="@+id/imv_led_palettle"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:src="@mipmap/img_led_palette" />

android:id="@+id/rl_led_switch"

android:layout_width="match_parent"

android:layout_height="58dp"

android:layout_marginLeft="24dp"

android:layout_marginRight="24dp"

android:orientation="horizontal"

android:layout_marginTop="30dp"

android:background="@drawable/shape_list_border"

android:layout_below="@+id/rl_led_paletle"

android:layout_centerHorizontal="true">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:paddingLeft="12dp"

android:text=" 彩灯开关" />

android:id="@+id/cb_contrl_led"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginRight="12dp"

android:layout_alignParentRight="true"

android:layout_centerVertical="true"

android:button="@null"

android:checked="true"

android:background="@drawable/selector_color"/>

android:layout_below="@id/rl_led_switch"

android:layout_width="match_parent"

android:layout_height="58dp"

android:layout_marginLeft="24dp"

android:layout_marginRight="24dp"

android:orientation="horizontal"

android:background="@drawable/shape_list_border"

android:layout_centerHorizontal="true"

android:gravity="center_horizontal"

>

android:id="@+id/tv_set_alpha"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:paddingLeft="12dp"

android:text=" 亮度调节" />

android:id="@+id/id_alpha_seek_bar"

android:layout_width="0dp"

android:layout_weight="1"

android:layout_height="wrap_content"

android:layout_alignRight="@id/tv_set_alpha"

android:layout_gravity="center_vertical"

android:progress="255"

android:max="255"

/>

android 自定义圆角头像以及使用declare-styleable进行配置属性解析

android 自定义圆角头像以及使用declare-styleable进行配置属性解析由于最新项目中正在检查UI是否与效果图匹配,结果关于联系人模块给的默认图片是四角稍带弧度的圆角,而我们截取的图片是正方形的,现在要给应用统一替换。应用中既用到大圆角头像(即整个头像是圆的)又用到四角稍带弧度的圆角头像,封装一下以便重用。以下直接见代码 [java] view plain copy 在CODE上查看代码片派生到我的代码片 package com.test.demo; import com.test.demo.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.widget.ImageView; /** * 圆角imageview */ public class RoundImageView extends ImageView { private static final String TAG = "RoundImageView"; /** * 图片的类型,圆形or圆角 */ private int type; public static final int TYPE_CIRCLE = 0; public static final int TYPE_ROUND = 1; /** * 圆角大小的默认值

android studio 控件常用属性

android studio 控件常用属性 下面是RelativeLayout各个属性 1.android:layout_above="@id/xxx" --将控件置于给定ID控件之上 2.android:layout_below="@id/xxx" --将控件置于给定ID控件之下 3. android:layout_toLeftOf="@id/xxx" --将控件的右边缘和给定ID控件的左边缘对齐 4.android:layout_toRightOf="@id/xxx" --将控件的左边缘和给定ID控件的右边缘对齐 5. android:layout_alignLeft="@id/xxx" --将控件的左边缘和给定ID控件的左边缘对齐 6.android:layout_alignTop="@id/xxx" --将控件的上边缘和给定ID控件的上边缘对齐 7.android:layout_alignRight="@id/xxx" --将控件的右边缘和给定ID控件的右边缘对齐 8.android:layout_alignBottom="@id/xxx" --将控件的底边缘和给定ID控件的底边缘对齐 9.android:layout_alignParentLeft="true" --将控件的左边缘和父控件的左边缘对齐 10. android:layout_alignParentTop="true" --将控件的上边缘和父控件的上边缘对齐 11. android:layout_alignParentRight="true" --将控件的右边缘和父控件的右边缘对齐 12.android:layout_alignParentBottom="true" --将控件的底边缘和父控件的底边缘对齐 13.android:layout_centerInParent="true" --将控件置于父控件的中心位置 14.android:layout_centerHorizontal="true" --将控件置于水平方向的中心位置 15.android:layout_centerVertical="true" --将控件置于垂直方向的中心位置 android:layout_width 设置组件的宽度 android:layout_height 设置组件的高度 android:id 给组件定义一个id值,供后期使用 android:background 设置组件的背景颜色或背景图片 android:text 设置组件的显示文字 android:textColor 设置组件的显示文字的颜色 android:layout_below 组件在参考组件的下面 android:alignTop 同指定组件的顶平行

Android平台我的日记设计文档

Android平台我的日记 设计文档 项目名称:mydiray 项目结构示意: 阶段任务名称(一)布局的设计 开始时间: 结束时间: 设计者: 梁凌旭 一、本次任务完成的功能 1、各控件的显示 二、最终功能及效果 三、涉及知识点介绍 四、代码设计 activity_main.xml:

android:layout_centerHorizontal="true" android:layout_marginTop="88dp" android:text="@string/wo" android:textSize="35sp"/>