放大Android渐变可绘制的中心

时间:2017-03-16 11:45:43

标签: android xml gradient android-drawable

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

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
    jcenter()
}
dependencies {
    classpath 'com.android.tools.build:gradle:2.3.0'
    classpath 'com.google.gms:google-services:3.0.0'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
}

allprojects {
repositories {
    jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir

渲染的渐变如下所示:

gradient image

如您所见,黑色部分扩散到大部分屏幕。我希望黑色仅显示在顶部和底部的一小部分上。有没有办法让透明中心变大,或者让顶部和底部的黑色条纹变小?

我尝试使用链接的<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> 文档中提到的一些其他XML属性,但它们似乎没有任何结果。

3 个答案:

答案 0 :(得分:3)

以下是使用自定义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;
    }
}

答案 1 :(得分:2)

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

以下代码会创建两个重叠的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>

感谢@Luksprog提供代码帮助,感谢@thenaoh提供了理念。

上述解决方案有效,并且很好,它们是纯XML。如果您的渐变显示条纹,您可能需要尝试编程解决方案,如@lelloman's答案中所示,以创建更平滑的渐变。

答案 2 :(得分:0)

有一个解决方案,假设你事先知道你的视图高度(让我们说这里是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);
    }
}

希望它有所帮助。