放大 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
对象并使用 centerY
和 centerColor
来抵消黑色部分。这里,centerY
属性设置为 0.9
和 0.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。如果您的渐变显示有条纹,您可能想尝试一种编程解决方案,如 答案中所示,以创建更平滑的渐变。
我创建了一个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
对象并使用 centerY
和 centerColor
来抵消黑色部分。这里,centerY
属性设置为 0.9
和 0.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>
谢谢
以上解决方案有效,很高兴它们是纯粹的 XML。如果您的渐变显示有条纹,您可能想尝试一种编程解决方案,如