放大 Android 渐变可绘制对象的中心

Enlarge the center of an Android gradient drawable

我创建了一个Android gradient drawable,其中顶部和底部是黑色的,中间是透明的:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:startColor="@android:color/black"
        android:centerColor="@android:color/transparent"
        android:endColor="@android:color/black"
        android:angle="90"/>
</shape>

渲染的渐变看起来像这样:

如您所见,黑色部分扩散到大部分屏幕。我希望黑色仅显示在顶部和底部的一小部分。有什么方法可以把中间的透明部分变大,或者把上下的黑色条纹变小?

我尝试使用链接的 GradientDrawable 文档中提到的其他一些 XML 属性,但其中 none 似乎有所作为。

有一个解决方案,假设您事先知道视图的高度(假设这里是 60dp):

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:bottom="40dp">
    <shape android:shape="rectangle">
        <gradient
            android:type="linear"
            android:angle="90"
            android:startColor="#FFFFFF"
            android:endColor="#000000"/>
    </shape>
</item>
<item
    android:top="20dp"
    android:bottom="20dp"
    android:gravity="center_vertical">
    <shape android:shape="rectangle">
        <solid android:color="#FFFFFF"/>
    </shape>
</item>
<item
    android:top="40dp"
    android:gravity="bottom">
    <shape android:shape="rectangle">
        <gradient
            android:type="linear"
            android:angle="90"
            android:startColor="#000000"
            android:endColor="#FFFFFF"/>
    </shape>
</item>
</layer-list>

但如果您事先不知道高度,另一种解决方案是制作您自己的自定义视图,如下所示:

public class MyView extends ImageView
{
    private Paint paint = null;

    public MyView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        paint.setShader(getLinearGradient(0, getHeight()));
        canvas.drawPaint(paint);
    }

    private LinearGradient getLinearGradient(float y0, float y1)
    {
        // colors :
        int[] listeColors = new int[3];
        listeColors[0] = 0xFF000000;
        listeColors[1] = 0xFFFFFFFF;
        listeColors[2] = 0xFFFFFFFF;

        // positions :
        float[] listPositions = new float[3];
        listPositions[0] = 0;
        listPositions[1] = 0.25F;
        listPositions[2] = 1;

        // gradient :
        return new LinearGradient(0, y0, 0, y0 + (y1 - y0) / 2, listeColors, listPositions, Shader.TileMode.MIRROR);
    }
}

希望对您有所帮助。

这里是如何使用自定义 Drawable 完成的。您可以根据需要调整 LinearGradient,然后使用 view.setBackground(new CustomDrawable());.

将其设置为视图的背景
public class CustomDrawable extends Drawable {

    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int[] colors;
    private float[] positions;

    public CustomDrawable() {
        paint.setStyle(Paint.Style.FILL);
        this.colors = new int[]{0xff000000, 0xffaaaaaa, 0xffffffff, 0xffaaaaaa, 0xff000000};
        this.positions = new float[]{.0f, .2f, .5f, .8f, 1.f};
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);    

        LinearGradient linearGradient = new LinearGradient(left, top,left, bottom, colors, positions, Shader.TileMode.CLAMP);
        paint.setShader(linearGradient);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {    
        canvas.drawRect(getBounds(), paint);
    }

    @Override
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
        paint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        paint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSPARENT;
    }
}

对于仅 XML 的解决方案,您可以使用两个单独的 gradient 对象创建一个 layer-list

以下代码创建两个重叠的 gradient 对象并使用 centerYcenterColor 来抵消黑色部分。这里,centerY 属性设置为 0.90.1,因此黑色限制在视图高度的顶部和底部 10%。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:angle="90"
                android:centerColor="@android:color/transparent"
                android:centerY="0.9"
                android:endColor="@android:color/black"
                android:startColor="@android:color/transparent" />
        </shape>
    </item>

    <item>
        <shape>
            <gradient
                android:angle="90"
                android:centerColor="@android:color/transparent"
                android:centerY="0.1"
                android:endColor="@android:color/transparent"
                android:startColor="@android:color/black" />
        </shape>
    </item>
</layer-list>

对于 API 级别 23 或更高级别,以下解决方案也适用,使用 android:height。即使您不知道视图的总高度,只要知道渐变的大小,此解决方案也可以使用。

此代码创建两个单独的渐变,每个渐变的高度为 60sp,然后使用 android:gravity 将渐变浮动到视图的顶部和底部。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:height="60sp"
        android:gravity="top">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@android:color/black"
                android:startColor="@android:color/transparent" />
        </shape>
    </item>
    <item
        android:height="65sp"
        android:gravity="bottom">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@android:color/transparent"
                android:startColor="@android:color/black" />
        </shape>
    </item>
</layer-list>

谢谢 for the code help, and 提出这个想法。

以上解决方案有效,很高兴它们是纯粹的 XML。如果您的渐变显示有条纹,您可能想尝试一种编程解决方案,如 答案中所示,以创建更平滑的渐变。