Android 具有渐变透明背景的线性布局
Android linear layout with gradient transparency background
如何在 android 透明渐变背景中给出线性布局,布局当前有一个模糊图像作为背景,但是我需要模糊图像在布局顶部稍微透明,然后去它底部的不透明。
布局嵌套在视差滚动视图中,因此布局可以滑过 header 图片的顶部。
我像这样生成模糊的可绘制对象:
final View content = img_header;
if (content.getWidth() > 0) {
Bitmap image = BlurBuilder.blur(content);
BitmapDrawable background = new BitmapDrawable(image);
ll_parent_layout.setBackground(background);
} else {
content.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Bitmap image = BlurBuilder.blur(content);
BitmapDrawable background = new BitmapDrawable(image);
ll_parent_layout.setBackground(background);
}
});
}
模糊生成器如下所示:
public class BlurBuilder {
private static final float BITMAP_SCALE = 1f;
private static final float BLUR_RADIUS = 25f;
public static Bitmap blur(View v) {
return blur(v.getContext(), getScreenshot(v));
}
public static Bitmap blur(Context ctx, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
/// compress bitmap here
RenderScript rs = RenderScript.create(ctx);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
public static Bitmap blur(Context ctx, Bitmap image, float scale, float radius) {
int width = Math.round(image.getWidth() * scale);
int height = Math.round(image.getHeight() * scale);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(ctx);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(radius);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
private static Bitmap getScreenshot(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
}
您可以使用 drawable xml 为您的布局设置渐变,如下所示。
将下面的代码放在文件中说 mybg.xml 并将其放入 drawable 文件夹中。
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient
android:startColor="@color/mycolor1"
android:endColor="@color/mycolor2"
android:angle="270" />
</shape>
对颜色使用 8 个字符的哈希码,这样您的颜色就可以像这样
mycolor1 -> #000000aa //this will give you transparent colored background
mycolor2 -> #ff00aa00 //this will be opaque like background
此处的前两个字符设置颜色的 alpha 级别。
由于您正在操纵 Bitmap
生成模糊图像,您可以使用 LinearGradient
着色器为其添加透明度,如 this answer.
public Bitmap addGradient(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap overlay = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, 0, 0, h, 0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.REPEAT);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawRect(0, h - h, w, h, paint);
return overlay;
}
可以这样做:
只需确保位图是可变的,
同样使用 fadingPortion 值(>= 0 和 <=1)你可以只使背景渐变的一部分透明
public static Bitmap makeBitmapTransparent(Bitmap mutableBitmap, float fadingPortion) {
final Shader gradientShader = new LinearGradient(
mutableBitmap.getWidth() / 2, 0,
mutableBitmap.getWidth() / 2, mutableBitmap.getHeight() * fadingPortion,
0x00000000, 0xFF000000,
Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(gradientShader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
Canvas canvas = new Canvas(mutableBitmap);
canvas.drawRect(new Rect(0, 0, mutableBitmap.getWidth(), (int) (mutableBitmap.getHeight() * FADING_PORTION)), paint);
canvas.drawBitmap(mutableBitmap, 0, 0, null);
return mutableBitmap;
}
如何在 android 透明渐变背景中给出线性布局,布局当前有一个模糊图像作为背景,但是我需要模糊图像在布局顶部稍微透明,然后去它底部的不透明。
布局嵌套在视差滚动视图中,因此布局可以滑过 header 图片的顶部。
我像这样生成模糊的可绘制对象:
final View content = img_header;
if (content.getWidth() > 0) {
Bitmap image = BlurBuilder.blur(content);
BitmapDrawable background = new BitmapDrawable(image);
ll_parent_layout.setBackground(background);
} else {
content.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Bitmap image = BlurBuilder.blur(content);
BitmapDrawable background = new BitmapDrawable(image);
ll_parent_layout.setBackground(background);
}
});
}
模糊生成器如下所示:
public class BlurBuilder {
private static final float BITMAP_SCALE = 1f;
private static final float BLUR_RADIUS = 25f;
public static Bitmap blur(View v) {
return blur(v.getContext(), getScreenshot(v));
}
public static Bitmap blur(Context ctx, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
/// compress bitmap here
RenderScript rs = RenderScript.create(ctx);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
public static Bitmap blur(Context ctx, Bitmap image, float scale, float radius) {
int width = Math.round(image.getWidth() * scale);
int height = Math.round(image.getHeight() * scale);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(ctx);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(radius);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
private static Bitmap getScreenshot(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
}
您可以使用 drawable xml 为您的布局设置渐变,如下所示。
将下面的代码放在文件中说 mybg.xml 并将其放入 drawable 文件夹中。
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient
android:startColor="@color/mycolor1"
android:endColor="@color/mycolor2"
android:angle="270" />
</shape>
对颜色使用 8 个字符的哈希码,这样您的颜色就可以像这样
mycolor1 -> #000000aa //this will give you transparent colored background
mycolor2 -> #ff00aa00 //this will be opaque like background
此处的前两个字符设置颜色的 alpha 级别。
由于您正在操纵 Bitmap
生成模糊图像,您可以使用 LinearGradient
着色器为其添加透明度,如 this answer.
public Bitmap addGradient(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap overlay = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, 0, 0, h, 0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.REPEAT);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawRect(0, h - h, w, h, paint);
return overlay;
}
可以这样做:
只需确保位图是可变的, 同样使用 fadingPortion 值(>= 0 和 <=1)你可以只使背景渐变的一部分透明
public static Bitmap makeBitmapTransparent(Bitmap mutableBitmap, float fadingPortion) {
final Shader gradientShader = new LinearGradient(
mutableBitmap.getWidth() / 2, 0,
mutableBitmap.getWidth() / 2, mutableBitmap.getHeight() * fadingPortion,
0x00000000, 0xFF000000,
Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(gradientShader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
Canvas canvas = new Canvas(mutableBitmap);
canvas.drawRect(new Rect(0, 0, mutableBitmap.getWidth(), (int) (mutableBitmap.getHeight() * FADING_PORTION)), paint);
canvas.drawBitmap(mutableBitmap, 0, 0, null);
return mutableBitmap;
}