下面列出了android.graphics.Shader#setLocalMatrix ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void invalidateIcons() {
mIconMatrices = new Matrix[mIconShaders.length];
mIconPaints = new Paint[mIconShaders.length];
for (int i = 0; i < mIconShaders.length; i++) {
Shader shader = mIconShaders[i];
Matrix matrix = new Matrix();
shader.setLocalMatrix(matrix);
mIconMatrices[i] = matrix;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(shader);
mIconPaints[i] = paint;
}
}
@Override
public CloseableReference<Bitmap> process(Bitmap source, PlatformBitmapFactory bitmapFactory) {
final Rect destRect = new Rect(0, 0, getWidth(), getHeight());
mScaleType.getTransform(
sTileMatrix,
destRect,
source.getWidth(),
source.getHeight(),
0.0f,
0.0f);
Paint paint = new Paint();
paint.setAntiAlias(true);
Shader shader = new BitmapShader(source, mTileMode, mTileMode);
shader.setLocalMatrix(sTileMatrix);
paint.setShader(shader);
CloseableReference<Bitmap> output = bitmapFactory.createBitmap(getWidth(), getHeight());
try {
Canvas canvas = new Canvas(output.get());
canvas.drawRect(destRect, paint);
return output.clone();
} finally {
CloseableReference.closeSafely(output);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (null == originMaskPath) {
// if the mask is null, the view will work as a normal ImageView
super.onDraw(canvas);
return;
}
if (vWidth == 0 || vHeight == 0) {
return;
}
paint.reset();
paint.setStyle(Paint.Style.STROKE);
//get the drawable to show. if not set the src, will use backColor
Drawable showDrawable = getDrawable();
if (null != showDrawable) {
Bitmap showBitmap = ((BitmapDrawable) showDrawable).getBitmap();
Shader shader = new BitmapShader(showBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Matrix shaderMatrix = new Matrix();
float scaleX = vWidth * 1.0f / showBitmap.getWidth();
float scaleY = vHeight * 1.0f / showBitmap.getHeight();
shaderMatrix.setScale(scaleX, scaleY);
shader.setLocalMatrix(shaderMatrix);
paint.setShader(shader);
} else {
//no src , use the backColor to fill the path
paint.setColor(backColor);
}
canvas.drawPath(realMaskPath, paint);
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
@Override
public void updateDrawState(TextPaint paint) {
paint.setStyle(Paint.Style.FILL);
Shader shader = new LinearGradient(0, 0, 0, paint.getTextSize() * colors.length, colors, null,
Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(90);
shader.setLocalMatrix(matrix);
paint.setShader(shader);
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void updateDrawState(TextPaint paint) {
paint.setStyle(Paint.Style.FILL);
Shader shader = new LinearGradient(0, 0, 0, paint.getTextSize()
* colors.length, colors, null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(90);
shader.setLocalMatrix(matrix);
paint.setShader(shader);
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void updateDrawState(TextPaint paint) {
paint.setStyle(Paint.Style.FILL);
Shader shader = new LinearGradient(0, 0, 0, paint.getTextSize()
* colors.length, colors, null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(90);
shader.setLocalMatrix(matrix);
paint.setShader(shader);
}
public void setupPaint(Paint paint, RectF box, float scale, float opacity) {
float height = box.height();
float width = box.width();
float midX = box.centerX();
float midY = box.centerY();
float offsetX = (midX - width / 2);
float offsetY = (midY - height / 2);
int[] stopsColors = mStopColors;
float[] stops = mStops;
//parseGradientStops(mColors, stopsCount, stops, stopsColors, opacity);
if (mType == GradientType.LINEAR_GRADIENT) {
float x1 = ParserHelper.fromPercentageToFloat(mPoints.get(0), width, offsetX, scale);
float y1 = ParserHelper.fromPercentageToFloat(mPoints.get(1), height, offsetY, scale);
float x2 = ParserHelper.fromPercentageToFloat(mPoints.get(2), width, offsetX, scale);
float y2 = ParserHelper.fromPercentageToFloat(mPoints.get(3), height, offsetY, scale);
paint.setShader(
new LinearGradient(
x1,
y1,
x2,
y2,
stopsColors,
stops,
Shader.TileMode.CLAMP));
} else {
float rx = ParserHelper.fromPercentageToFloat(mPoints.get(2), width, 0f, scale);
float ry = ParserHelper.fromPercentageToFloat(mPoints.get(3), height, 0f, scale);
float cx = ParserHelper.fromPercentageToFloat(mPoints.get(4), width, offsetX, scale);
float cy = ParserHelper.fromPercentageToFloat(mPoints.get(5), height, offsetY, scale) / (ry / rx);
// TODO: support focus point.
float fx = ParserHelper.fromPercentageToFloat(mPoints.get(0), width, offsetX, scale);
float fy = ParserHelper.fromPercentageToFloat(mPoints.get(1), height, offsetY, scale) / (ry / rx);
Shader radialGradient = new RadialGradient(
cx,
cy,
rx,
stopsColors,
stops,
Shader.TileMode.CLAMP
);
Matrix radialMatrix = new Matrix();
radialMatrix.preScale(1f, ry / rx);
radialGradient.setLocalMatrix(radialMatrix);
paint.setShader(radialGradient);
}
}
@SuppressWarnings("deprecation")
private void doStroke(Path path)
{
// TODO handle degenerate subpaths properly
if (state.style.vectorEffect == VectorEffect.NonScalingStroke)
{
// For non-scaling-stroke, the stroke width is not transformed along with the path.
// It will be rendered at the same width no matter how the document contents are transformed.
// First step: get the current canvas matrix
Matrix currentMatrix = canvas.getMatrix();
// Transform the path using this transform
Path transformedPath = new Path();
path.transform(currentMatrix, transformedPath);
// Reset the current canvas transform completely
canvas.setMatrix(new Matrix());
// If there is a shader (such as a gradient), we need to update its transform also
Shader shader = state.strokePaint.getShader();
Matrix currentShaderMatrix = new Matrix();
if (shader != null) {
shader.getLocalMatrix(currentShaderMatrix);
Matrix newShaderMatrix = new Matrix(currentShaderMatrix);
newShaderMatrix.postConcat(currentMatrix);
shader.setLocalMatrix(newShaderMatrix);
}
// Render the transformed path. The stroke width used will be in unscaled device units.
canvas.drawPath(transformedPath, state.strokePaint);
// Return the current canvas transform to what it was before all this happened
canvas.setMatrix(currentMatrix);
// And reset the shader matrix also
if (shader != null)
shader.setLocalMatrix(currentShaderMatrix);
}
else
{
canvas.drawPath(path, state.strokePaint);
}
}
@SuppressWarnings("deprecation")
private void doStroke(Path path)
{
// TODO handle degenerate subpaths properly
if (state.style.vectorEffect == VectorEffect.NonScalingStroke)
{
// For non-scaling-stroke, the stroke width is not transformed along with the path.
// It will be rendered at the same width no matter how the document contents are transformed.
// First step: get the current canvas matrix
Matrix currentMatrix = canvas.getMatrix();
// Transform the path using this transform
Path transformedPath = new Path();
path.transform(currentMatrix, transformedPath);
// Reset the current canvas transform completely
canvas.setMatrix(new Matrix());
// If there is a shader (such as a gradient), we need to update its transform also
Shader shader = state.strokePaint.getShader();
Matrix currentShaderMatrix = new Matrix();
if (shader != null) {
shader.getLocalMatrix(currentShaderMatrix);
Matrix newShaderMatrix = new Matrix(currentShaderMatrix);
newShaderMatrix.postConcat(currentMatrix);
shader.setLocalMatrix(newShaderMatrix);
}
// Render the transformed path. The stroke width used will be in unscaled device units.
canvas.drawPath(transformedPath, state.strokePaint);
// Return the current canvas transform to what it was before all this happened
canvas.setMatrix(currentMatrix);
// And reset the shader matrix also
if (shader != null)
shader.setLocalMatrix(currentShaderMatrix);
}
else
{
canvas.drawPath(path, state.strokePaint);
}
}
private synchronized void prepareDrawTime() {
Log.d(TAG, "CircleWatchface start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
;
rect = new RectF(PADDING, PADDING, (float) (displaySize.x - PADDING), (float) (displaySize.y - PADDING));
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, (float) (displaySize.x - PADDING + CIRCLE_WIDTH / 2), (float) (displaySize.y - PADDING + CIRCLE_WIDTH / 2));
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d(TAG, "CircleWatchface end prepareDrawTime");
}
private synchronized void prepareDrawTime() {
Log.d(TAG, "CircleWatchface start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
;
rect = new RectF(PADDING, PADDING, (float) (displaySize.x - PADDING), (float) (displaySize.y - PADDING));
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, (float) (displaySize.x - PADDING + CIRCLE_WIDTH / 2), (float) (displaySize.y - PADDING + CIRCLE_WIDTH / 2));
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d(TAG, "CircleWatchface end prepareDrawTime");
}
private synchronized void prepareDrawTime() {
Log.d("CircleWatchface", "start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
;
rect = new RectF(PADDING, PADDING, (float) (displaySize.x - PADDING), (float) (displaySize.y - PADDING));
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, (float) (displaySize.x - PADDING + CIRCLE_WIDTH / 2), (float) (displaySize.y - PADDING + CIRCLE_WIDTH / 2));
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d("CircleWatchface", "end prepareDrawTime");
}
private synchronized void prepareDrawTime() {
Log.d("CircleWatchface", "start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
rect = new RectF(PADDING, PADDING, displaySize.x - PADDING, displaySize.y - PADDING);
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, displaySize.x - PADDING + CIRCLE_WIDTH / 2, displaySize.y - PADDING + CIRCLE_WIDTH / 2);
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d("CircleWatchface", "end prepareDrawTime");
}
private synchronized void prepareDrawTime() {
Log.d("CircleWatchface", "start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
;
rect = new RectF(PADDING, PADDING, (float) (displaySize.x - PADDING), (float) (displaySize.y - PADDING));
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, (float) (displaySize.x - PADDING + CIRCLE_WIDTH / 2), (float) (displaySize.y - PADDING + CIRCLE_WIDTH / 2));
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d("CircleWatchface", "end prepareDrawTime");
}
@SuppressWarnings("deprecation")
private void doStroke(Path path)
{
// TODO handle degenerate subpaths properly
if (state.style.vectorEffect == VectorEffect.NonScalingStroke)
{
// For non-scaling-stroke, the stroke width is not transformed along with the path.
// It will be rendered at the same width no matter how the document contents are transformed.
// First step: get the current canvas matrix
Matrix currentMatrix = canvas.getMatrix();
// Transform the path using this transform
Path transformedPath = new Path();
path.transform(currentMatrix, transformedPath);
// Reset the current canvas transform completely
canvas.setMatrix(new Matrix());
// If there is a shader (such as a gradient), we need to update its transform also
Shader shader = state.strokePaint.getShader();
Matrix currentShaderMatrix = new Matrix();
if (shader != null) {
shader.getLocalMatrix(currentShaderMatrix);
Matrix newShaderMatrix = new Matrix(currentShaderMatrix);
newShaderMatrix.postConcat(currentMatrix);
shader.setLocalMatrix(newShaderMatrix);
}
// Render the transformed path. The stroke width used will be in unscaled device units.
canvas.drawPath(transformedPath, state.strokePaint);
// Return the current canvas transform to what it was before all this happened
canvas.setMatrix(currentMatrix);
// And reset the shader matrix also
if (shader != null)
shader.setLocalMatrix(currentShaderMatrix);
}
else
{
canvas.drawPath(path, state.strokePaint);
}
}