3

How can I give a linear layout in android transparent gradient background, the layout currently has a blurred image as its background however i need the blurred image to be slightly transparent at the top of the layout and then go to opaque at the bottom of it.

The layout is nested in a parallax scrollview so the layout can slide over the top of the header image.

I generate the blurred drawable like so:

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

The blur builder looks like this:

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;
}
}
MichaelStoddart
  • 5,571
  • 4
  • 27
  • 49

3 Answers3

4

Since you are manipulating Bitmap to generate the blurred image, you can use a LinearGradient shader to add transparency to it as in 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;
}
Community
  • 1
  • 1
bradkratky
  • 1,577
  • 1
  • 14
  • 28
  • Worked like a charm, i've been looking for a solution for this for at least a week! – MichaelStoddart Jul 13 '16 at 15:42
  • Im having an issue with this solution now, it seems that on backgrounds where the blurred image is black you can see a line where the gradient starts, have you ever had this issue before? – MichaelStoddart Aug 01 '16 at 14:29
  • Is it possible to use this on a RelativeLayout instead of a Bitmap? – Henning Hall May 27 '18 at 19:46
  • @HenningHall I think so, by drawing the layout (which is a View) onto the Canvas instead of the bitmap. I'm not sure how performant this would be. https://developer.android.com/reference/android/view/View#draw – bradkratky May 30 '18 at 12:17
0

You can use drawable xml to set the gradient to your layout as below.

Place below code in file say mybg.xml and put it inside drawable folder.

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

use 8 char hashcode for colors so your colors can be like this

mycolor1 -> #000000aa   //this will give you transparent colored background
mycolor2 -> #ff00aa00   //this will be opaque like background

first two chars here set the alpha level for color.

karan
  • 8,637
  • 3
  • 41
  • 78
0

can do it this way:

just make sure Bitmap is mutable, also using fadingPortion value (>= 0 and <=1) you can make only part of background gradient transparent

    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;
}
Sharpe
  • 406
  • 4
  • 8