我正在创建一个没有填充但是渐变笔划的按钮。作为参考,这是我追求的最终结果:
我想知道如何使用渐变笔划创建这样一个按钮,而不是以编程方式填充。我查看了GradientDrawable
类和其中的setStroke()
方法。似乎没有人允许这样做。有没有办法以编程方式执行此操作或根本不可能执行此操作?
答案 0 :(得分:2)
我为你尝试过一些东西..
使用mRect.set
设置路径,mPath.addRoundRect
添加矩形。使用setShader
代替strock link
Drawable class:
public class CustomDrawable extends Drawable {
Paint mPaint;
int startColor, endColor, mBorderWidth, mBorderRadius;
RectF mRect;
Path mPath;
public CustomDrawable(int startColor, int endColor, int borderWidth, int borderRadius) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
mPath.setFillType(Path.FillType.EVEN_ODD);
mRect = new RectF();
this.startColor = startColor;
this.endColor = endColor;
mBorderWidth = borderWidth;
mBorderRadius = borderRadius;
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mPath.reset();
// out rect
mRect.set(bounds.left + mBorderWidth, bounds.top + mBorderWidth, bounds.right - mBorderWidth, bounds.bottom - mBorderWidth);
mPath.addRoundRect(mRect, mBorderRadius, mBorderRadius, Path.Direction.CW);
// inner rect
mRect.set(bounds.left + 20, bounds.top + 20, bounds.right - 20, bounds.bottom - 20);
mPath.addRoundRect(mRect, mBorderRadius, mBorderRadius, Path.Direction.CW);
}
@Override
public void draw(@NonNull Canvas canvas) {
// kind of strock
mPaint.setShader(new LinearGradient(0, 0, 0, 100, startColor, endColor, Shader.TileMode.MIRROR));
canvas.drawPath(mPath, mPaint);
}
@Override
public void setAlpha(int alpha) { mPaint.setAlpha(alpha);}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {mPaint.setColorFilter(colorFilter);}
@Override
public int getOpacity() {return PixelFormat.TRANSLUCENT;}
}
主要:
Button but = ((Button)findViewById(R.id.but));
but.setBackground(new CustomDrawable(Color.parseColor("#FD659B"),
Color.parseColor("#F76E63"),
but.getPaddingLeft(), 100));
布局:
<Button
android:id="@+id/but"
android:layout_width="300dp"
android:layout_height="80dp"
android:background="@android:color/transparent"
android:layout_centerInParent="true"
android:text="Signin"/>
答案 1 :(得分:1)
这是@ lamat8贡献的又一步:
import android.graphics.*
import android.graphics.Paint.ANTI_ALIAS_FLAG
import android.graphics.Path.FillType
import android.graphics.drawable.Drawable
import androidx.annotation.NonNull
import java.lang.RuntimeException
class GradientDrawable(
private var strokeStartColor: Int,
private var strokeEndColor: Int,
private var fillStartColor: Int,
private var fillEndColor: Int,
private var strokeWidth: Float,
private var radius: Float,
private var strokeGradientDirection: Direction,
private var fillGradientDirection: Direction
) : Drawable() {
enum class Direction {
LEFT_RIGHT,
TOP_BOTTOM,
RIGHT_LEFT,
BOTTOM_TOP,
TL_BR,
TR_BL,
BR_TL,
BL_TR
}
private val strokePaint: Paint = Paint(ANTI_ALIAS_FLAG)
private val fillPaint: Paint = Paint(ANTI_ALIAS_FLAG)
private val strokeOuterRect = RectF()
private val fillRect = RectF()
private val path = Path()
init {
strokePaint.style = Paint.Style.FILL
path.fillType = FillType.EVEN_ODD
}
override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
path.reset()
strokeOuterRect.set(bounds)
fillRect.set(
bounds.left + strokeWidth,
bounds.top + strokeWidth,
bounds.right - strokeWidth,
bounds.bottom - strokeWidth
)
path.addRoundRect(
strokeOuterRect,
radius,
radius,
Path.Direction.CW
)
path.addRoundRect(
fillRect,
radius,
radius,
Path.Direction.CW
)
}
override fun draw(@NonNull canvas: Canvas) {
var x0: Float
var y0: Float
var x1: Float
var y1: Float
// drawing the stroke
when (strokeGradientDirection) {
Direction.LEFT_RIGHT -> {
x0 = strokeOuterRect.left
y0 = strokeOuterRect.centerY()
x1 = strokeOuterRect.right
y1 = strokeOuterRect.centerY()
}
Direction.TOP_BOTTOM -> {
x0 = strokeOuterRect.centerX()
y0 = strokeOuterRect.top
x1 = strokeOuterRect.centerX()
y1 = strokeOuterRect.bottom
}
Direction.RIGHT_LEFT -> {
x0 = strokeOuterRect.right
y0 = strokeOuterRect.centerY()
x1 = strokeOuterRect.left
y1 = strokeOuterRect.centerY()
}
Direction.BOTTOM_TOP -> {
x0 = strokeOuterRect.centerX()
y0 = strokeOuterRect.bottom
x1 = strokeOuterRect.centerX()
y1 = strokeOuterRect.top
}
Direction.TL_BR -> {
x0 = strokeOuterRect.left
y0 = strokeOuterRect.top
x1 = strokeOuterRect.right
y1 = strokeOuterRect.bottom
}
Direction.TR_BL -> {
x0 = strokeOuterRect.right
y0 = strokeOuterRect.top
x1 = strokeOuterRect.left
y1 = strokeOuterRect.bottom
}
Direction.BR_TL -> {
x0 = strokeOuterRect.right
y0 = strokeOuterRect.bottom
x1 = strokeOuterRect.left
y1 = strokeOuterRect.top
}
Direction.BL_TR -> {
x0 = strokeOuterRect.left
y0 = strokeOuterRect.bottom
x1 = strokeOuterRect.right
y1 = strokeOuterRect.top
}
}
strokePaint.shader = LinearGradient(
x0,
y0,
x1,
y1,
strokeStartColor,
strokeEndColor,
Shader.TileMode.MIRROR
)
canvas.drawPath(path, strokePaint)
// filling the shape
when (fillGradientDirection) {
Direction.LEFT_RIGHT -> {
x0 = fillRect.left
y0 = fillRect.centerY()
x1 = fillRect.right
y1 = fillRect.centerY()
}
Direction.TOP_BOTTOM -> {
x0 = fillRect.centerX()
y0 = fillRect.top
x1 = fillRect.centerX()
y1 = fillRect.bottom
}
Direction.RIGHT_LEFT -> {
x0 = fillRect.right
y0 = fillRect.centerY()
x1 = fillRect.left
y1 = fillRect.centerY()
}
Direction.BOTTOM_TOP -> {
x0 = fillRect.centerX()
y0 = fillRect.bottom
x1 = fillRect.centerX()
y1 = fillRect.top
}
Direction.TL_BR -> {
x0 = fillRect.left
y0 = fillRect.top
x1 = fillRect.right
y1 = fillRect.bottom
}
Direction.TR_BL -> {
x0 = fillRect.right
y0 = fillRect.top
x1 = fillRect.left
y1 = fillRect.bottom
}
Direction.BR_TL -> {
x0 = fillRect.right
y0 = fillRect.bottom
x1 = fillRect.left
y1 = fillRect.top
}
Direction.BL_TR -> {
x0 = fillRect.left
y0 = fillRect.bottom
x1 = fillRect.right
y1 = fillRect.top
}
}
fillPaint.shader = LinearGradient(
x0,
y0,
x1,
y1,
fillStartColor,
fillEndColor,
Shader.TileMode.MIRROR
)
canvas.drawRoundRect(
fillRect,
radius,
radius,
fillPaint
)
}
override fun setAlpha(alpha: Int) {
strokePaint.alpha = alpha
fillPaint.alpha = alpha
invalidateSelf()
}
override fun setColorFilter(colorFilter: ColorFilter?) {
throw RuntimeException("Color filter cannot be set to this Drawable")
}
override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}
fun setStrokeColors(startColor: Int, endColor: Int) {
this.strokeStartColor = startColor
this.strokeEndColor = endColor
invalidateSelf()
}
fun setFillColors(startColor: Int, endColor: Int) {
this.fillStartColor = startColor
this.fillEndColor = endColor
invalidateSelf()
}
fun setRadius(radius: Float) {
this.radius = radius
invalidateSelf()
}
fun setStrokeWidth(width: Float) {
this.strokeWidth = width
invalidateSelf()
}
}
该类添加了以下功能:
答案 2 :(得分:0)
我认为我们不能为Stroke设置渐变,但我们可以使用图层列表进行相同的操作。
你可以使用你想要的渐变创建下面的可绘制xml
<item>
<shape android:shape="rectangle">
<!-- gradient for the stroke is set below -->
<gradient
android:angle="180"
android:startColor="#555994"
android:endColor="#b5b6d2"
android:type="linear" />
<corners android:radius="4dp"></corners>
</shape>
</item>
<!-- stroke width has to be adjusted by setting left, right , top and bottom -->
<item android:left="4dp" android:right="4dp"
android:top="4dp" android:bottom="4dp">
<shape
android:shape="rectangle">
<solid android:color="@android:color/white"/>
</shape>
</item>
您可以在布局/编程中设置上述drawable
<强> button.setBackgroundResource(R.drawable.button_background); 强>