mirror of
https://github.com/material-components/material-components-android.git
synced 2026-02-20 08:39:55 +08:00
* commit '75962f6207ea6f1404d44d0f75c48f7aa9c13adb': Re-enable border sheen (aka border) GitOrigin-RevId=58ca0d90dbcd10a254eb17bed3dd57ab4d111bd2 PiperOrigin-RevId: 140548857
175 lines
5.5 KiB
Java
175 lines
5.5 KiB
Java
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.support.design.widget;
|
|
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.LinearGradient;
|
|
import android.graphics.Paint;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.Rect;
|
|
import android.graphics.RectF;
|
|
import android.graphics.Shader;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.support.v4.graphics.ColorUtils;
|
|
|
|
/**
|
|
* A drawable which draws an oval 'border'.
|
|
*/
|
|
class CircularBorderDrawable extends Drawable {
|
|
|
|
/**
|
|
* We actually draw the stroke wider than the border size given. This is to reduce any
|
|
* potential transparent space caused by anti-aliasing and padding rounding.
|
|
* This value defines the multiplier used to determine to draw stroke width.
|
|
*/
|
|
private static final float DRAW_STROKE_WIDTH_MULTIPLE = 1.3333f;
|
|
|
|
final Paint mPaint;
|
|
final Rect mRect = new Rect();
|
|
final RectF mRectF = new RectF();
|
|
|
|
float mBorderWidth;
|
|
|
|
private int mTopOuterStrokeColor;
|
|
private int mTopInnerStrokeColor;
|
|
private int mBottomOuterStrokeColor;
|
|
private int mBottomInnerStrokeColor;
|
|
|
|
private int mTintColor;
|
|
|
|
private boolean mInvalidateShader = true;
|
|
|
|
public CircularBorderDrawable() {
|
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
mPaint.setStyle(Paint.Style.STROKE);
|
|
}
|
|
|
|
void setGradientColors(int topOuterStrokeColor, int topInnerStrokeColor,
|
|
int bottomOuterStrokeColor, int bottomInnerStrokeColor) {
|
|
mTopOuterStrokeColor = topOuterStrokeColor;
|
|
mTopInnerStrokeColor = topInnerStrokeColor;
|
|
mBottomOuterStrokeColor = bottomOuterStrokeColor;
|
|
mBottomInnerStrokeColor = bottomInnerStrokeColor;
|
|
}
|
|
|
|
/**
|
|
* Set the border width
|
|
*/
|
|
void setBorderWidth(float width) {
|
|
if (mBorderWidth != width) {
|
|
mBorderWidth = width;
|
|
mPaint.setStrokeWidth(width * DRAW_STROKE_WIDTH_MULTIPLE);
|
|
mInvalidateShader = true;
|
|
invalidateSelf();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void draw(Canvas canvas) {
|
|
if (mInvalidateShader) {
|
|
mPaint.setShader(createGradientShader());
|
|
mInvalidateShader = false;
|
|
}
|
|
|
|
final float halfBorderWidth = mPaint.getStrokeWidth() / 2f;
|
|
final RectF rectF = mRectF;
|
|
|
|
// We need to inset the oval bounds by half the border width. This is because stroke draws
|
|
// the center of the border on the dimension. Whereas we want the stroke on the inside.
|
|
copyBounds(mRect);
|
|
rectF.set(mRect);
|
|
rectF.left += halfBorderWidth;
|
|
rectF.top += halfBorderWidth;
|
|
rectF.right -= halfBorderWidth;
|
|
rectF.bottom -= halfBorderWidth;
|
|
|
|
// Draw the oval
|
|
canvas.drawOval(rectF, mPaint);
|
|
}
|
|
|
|
@Override
|
|
public boolean getPadding(Rect padding) {
|
|
final int borderWidth = Math.round(mBorderWidth);
|
|
padding.set(borderWidth, borderWidth, borderWidth, borderWidth);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
mPaint.setAlpha(alpha);
|
|
invalidateSelf();
|
|
}
|
|
|
|
void setTintColor(int tintColor) {
|
|
mTintColor = tintColor;
|
|
mInvalidateShader = true;
|
|
invalidateSelf();
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(ColorFilter colorFilter) {
|
|
mPaint.setColorFilter(colorFilter);
|
|
invalidateSelf();
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return mBorderWidth > 0 ? PixelFormat.TRANSLUCENT : PixelFormat.TRANSPARENT;
|
|
}
|
|
|
|
@Override
|
|
protected void onBoundsChange(Rect bounds) {
|
|
mInvalidateShader = true;
|
|
}
|
|
|
|
/**
|
|
* Creates a vertical {@link LinearGradient}
|
|
* @return
|
|
*/
|
|
private Shader createGradientShader() {
|
|
final Rect rect = mRect;
|
|
copyBounds(rect);
|
|
|
|
final float borderRatio = mBorderWidth / rect.height();
|
|
|
|
final int[] colors = new int[6];
|
|
colors[0] = ColorUtils.compositeColors(mTopOuterStrokeColor, mTintColor);
|
|
colors[1] = ColorUtils.compositeColors(mTopInnerStrokeColor, mTintColor);
|
|
colors[2] = ColorUtils.compositeColors(
|
|
ColorUtils.setAlphaComponent(mTopInnerStrokeColor, 0), mTintColor);
|
|
colors[3] = ColorUtils.compositeColors(
|
|
ColorUtils.setAlphaComponent(mBottomInnerStrokeColor, 0), mTintColor);
|
|
colors[4] = ColorUtils.compositeColors(mBottomInnerStrokeColor, mTintColor);
|
|
colors[5] = ColorUtils.compositeColors(mBottomOuterStrokeColor, mTintColor);
|
|
|
|
final float[] positions = new float[6];
|
|
positions[0] = 0f;
|
|
positions[1] = borderRatio;
|
|
positions[2] = 0.5f;
|
|
positions[3] = 0.5f;
|
|
positions[4] = 1f - borderRatio;
|
|
positions[5] = 1f;
|
|
|
|
return new LinearGradient(
|
|
0, rect.top,
|
|
0, rect.bottom,
|
|
colors, positions,
|
|
Shader.TileMode.CLAMP);
|
|
}
|
|
}
|