具有渐变透明背景的Android线性布局

3

我该如何在Android中给线性布局添加透明渐变背景?目前该布局的背景是模糊的图像,但我需要让该图像在布局顶部略微透明,并在底部变为不透明。

该布局嵌套在视差滚动视图中,因此该布局可以滑动到头部图像的顶部。

我通过以下方式生成了模糊的可绘制对象:

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代码吗? - karan
你没有使用可绘制资源吗? - karan
@KaranMer 不是模糊的图像从URL中拉取,设置在img_header ImageView中,然后被模糊并设置为ll_parent_layout的背景。 - MichaelStoddart
你尝试过使用哈希码来代替图像作为颜色吗? - karan
@KaranMer,你能给一个代码示例吗? - MichaelStoddart
显示剩余4条评论
3个回答

4

由于您正在操作Bitmap以生成模糊图像,因此可以使用LinearGradient着色器来添加透明度,例如此答案中所示。

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;
}

运行得非常好,我已经寻找解决方案至少一周了! - MichaelStoddart
我现在遇到了一个问题,似乎在背景为黑色的情况下,你可以看到渐变开始的线条,在此解决方案上。您以前遇到过这个问题吗? - MichaelStoddart
这个能否用在RelativeLayout上,而不是Bitmap上? - Henning Hall
@HenningHall 我认为可以通过将布局(即View)绘制到画布上而不是位图上来实现。但我不确定这样做的性能如何。https://developer.android.com/reference/android/view/View#draw - bradkratky

0

您可以使用可绘制的 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

这里的前两个字符设置颜色的透明度。


0
可以这样做:
只需确保Bitmap是可变的, 同时使用fadingPortion值(>= 0 and <=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;
}

我应该传递什么作为淡出部分? - MichaelStoddart
浮点数在0到1之间。例如,0.25表示只有上四分之一会逐渐变为透明。 - Sharpe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接