日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 自定义取色器,【Android自定义View】仿Photoshop取色器ColorPicker(二)

發布時間:2023/12/31 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 自定义取色器,【Android自定义View】仿Photoshop取色器ColorPicker(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ColorPicker

一款仿Photoshop取色器的Android版取色器。

前言

上一篇已經簡單介紹了ColorPicker的項目結構以及兩種顏色空間,接下來我們詳細解析一下ColorPicker的核心自定義控件ColorPickerView。

ColorPickerView

在閱讀代碼之前,我們先看一下ColorPicker的布局以及一些標注的數值在代碼里的變量名稱。

介紹

變量名

閱讀一個自定義View的代碼,只需記住四步走:構造方法、onMeasure、onLayout、onDraw

構造方法

public ColorPickerView(Context context) {

this(context, null);

}

public ColorPickerView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init();

}

可見,前2個構造器最后都調用了第三個構造器。而第三個構造器里的主要內容都在一個名為init()的方法。

private void init() {

mDensity = getContext().getResources().getDisplayMetrics().density;//獲取屏幕密度

mSVTrackerRadius *= mDensity;//灰度飽和度指示器的半徑

mRectOffset *= mDensity;//H、SV矩形與父布局的邊距

mHuePanelWidth *= mDensity;//H矩形的寬度

mPanelSpacing *= mDensity;//H、SV矩形間的間距

mPreferredHeight *= mDensity;//當mode為MeasureSpec.UNSPECIFIED時的首選高度

mPreferredWidth *= mDensity;//當mode為MeasureSpec.UNSPECIFIED時的首選寬度

mDrawingOffset = calculateRequiredOffset();//計算所需位移

initPaintTools();//初始化畫筆、畫布

setFocusable(true);//設置可獲取焦點

setFocusableInTouchMode(true);//設置在被觸摸時會獲取焦點

}

init方法里有很多變量,它們的含義如下圖所示:

變量名

onMeasure

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);

int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);

widthAllowed = isUnspecified(widthMode) ? (int) mPreferredWidth : widthAllowed;

heightAllowed = isUnspecified(heightMode) ? (int) mPreferredHeight : heightAllowed;

int width = widthAllowed;

int height = (int) (widthAllowed - mPanelSpacing - mHuePanelWidth);

//當根據寬度計算出來的高度大于可允許的最大高度時 或 當前是橫屏

if (height > heightAllowed || "landscape".equals(getTag())) {

height = heightAllowed;

width = (int) (height + mPanelSpacing + mHuePanelWidth);

}

setMeasuredDimension(width, height);

}

private static boolean isUnspecified(int mode) {

return !(mode == MeasureSpec.EXACTLY || mode == MeasureSpec.AT_MOST);

}

測量模式(MeasureSpecMode)分為EXACTLY、AT_MOST、UNSPECIFIED三種類型。前兩種類型可以通過MeasureSpec.getSize(int measureSpec)獲得具體的值;當測量模式為UNSPECIFIED時,需要我們自己確定自定義View的高寬。這里我設定了一些默認值,使ColorPicker看起來更舒服。

onLayout

這里使用了父類的onLayout方法。

onDraw

繪制ColorPickerView分為兩個部分:飽和度灰度調色板mSatValRect+色相調色板mHueRect。

@Override

protected void onDraw(Canvas canvas) {

if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return;

drawSatValPanel(canvas);//繪制SV選擇區域

drawHuePanel(canvas);//繪制右側H選擇區域

}

開始了解具體繪制細節之前,希望讀者已經了解過Shader(著色器)的相關知識。

繪制飽和度灰度調色板

1 先畫一個大矩形,再在上面畫我們的飽和度灰度調色板,這樣看起來有一個描邊的效果。

2 繪制飽和度灰度指示器。根據當前選擇的顏色定位到具體的坐標,在這個坐標上做畫。先畫一個半徑為mSVTrackerRadius、邊線粗細為mDensity的空心大圓,再在上面畫一個半徑為mSVTrackerRadius-mDensity、邊線粗細為mDensity的空心小圓。

/**

* 繪制S、V選擇區域(矩形)

*

* @param canvas 畫布

*/

private void drawSatValPanel(Canvas canvas) {

//描邊(先畫一個大矩形, 再在內部畫一個小矩形,就可以顯示出描邊的效果)

mBorderPaint.setColor(mBorderColor);

canvas.drawRect(

mDrawingRect.left,

mDrawingRect.top,

mSatValRect.right + BORDER_WIDTH,

mSatValRect.bottom + BORDER_WIDTH,

mBorderPaint);

//組合著色器 = 明度線性著色器 + 飽和度線性著色器

ComposeShader mShader = generateSVShader();

mSatValPaint.setShader(mShader);

canvas.drawRect(mSatValRect, mSatValPaint);

//初始化選擇器的位置

Point p = satValToPoint(mSat, mVal);

//繪制顯示SV值的選擇器

mSatValTrackerPaint.setColor(0xff000000);

canvas.drawCircle(p.x, p.y, mSVTrackerRadius - 1f * mDensity, mSatValTrackerPaint);

//繪制外圓

mSatValTrackerPaint.setColor(0xffdddddd);

canvas.drawCircle(p.x, p.y, mSVTrackerRadius, mSatValTrackerPaint);

}

/**

* 創建SV著色器(明度線性著色器 + 飽和度線性著色器)

*

* @return 著色器

*/

private ComposeShader generateSVShader() {

//明度線性著色器

if (mValShader == null) {

mValShader = new LinearGradient(mSatValRect.left, mSatValRect.top, mSatValRect.left, mSatValRect.bottom,

0xffffffff, 0xff000000, TileMode.CLAMP);

}

//HSV轉化為RGB

int rgb = Color.HSVToColor(new float[]{mHue, 1f, 1f});

//飽和線性著色器

Shader satShader = new LinearGradient(mSatValRect.left, mSatValRect.top, mSatValRect.right, mSatValRect.top,

0xffffffff, rgb, TileMode.CLAMP);

//組合著色器 = 明度線性著色器 + 飽和度線性著色器

return new ComposeShader(mValShader, satShader, PorterDuff.Mode.MULTIPLY);

}

繪制色相調色板

1 同理繪制矩形調色板

2 同理繪制空心圓角矩形

/**

* 繪制右側H選擇區域

*

* @param canvas 畫布

*/

private void drawHuePanel(Canvas canvas) {

final RectF rect = mHueRect;

mBorderPaint.setColor(mBorderColor);

canvas.drawRect(rect.left - BORDER_WIDTH,

rect.top - BORDER_WIDTH,

rect.right + BORDER_WIDTH,

rect.bottom + BORDER_WIDTH,

mBorderPaint);

//初始化H線性著色器

if (mHueShader == null) {

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

}

mHueShader = new LinearGradient(

rect.left,

rect.top,

rect.left,

rect.bottom,

hue,

null,

TileMode.CLAMP);

mHuePaint.setShader(mHueShader);

}

canvas.drawRect(rect, mHuePaint);

float halfHTrackerHeight= mHTrackerHeight / 2;

//初始化H選擇器選擇條位置

Point p = hueToPoint(mHue);

RectF r = new RectF();

r.left = rect.left - mRectOffset;

r.right = rect.right + mRectOffset;

r.top = p.y - halfHTrackerHeight;

r.bottom = p.y + halfHTrackerHeight;

//繪制選擇條

canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);

}

這樣一來,整個ColorPickerView的繪制流程就都在這里了。

下一篇主要講解ColorPickerView的初始化顏色傳入和顏色改變監聽回調:【Android自定義View】仿Photoshop取色器ColorPicker(三)

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的android 自定义取色器,【Android自定义View】仿Photoshop取色器ColorPicker(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。