9

I'm generating the bitmap of a view to show it as a marker on the Map. It is working fine but the issue that i'm facing is that elevation of the view is not showing.

private Bitmap getMarkerBitmapFromView(View view) {

        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        //view.buildDrawingCache();
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        Bitmap returnedBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(returnedBitmap);
        /*canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
        Drawable drawable = view.getBackground();
        if (drawable != null)
            drawable.draw(canvas);
        */
        view.draw(canvas);
        return returnedBitmap;

    }
Usman Rana
  • 2,067
  • 1
  • 21
  • 32
  • `but the issue that i'm facing is that elevation of the view is not showing.` so how you set the elevation to the marker view ? –  Jul 08 '18 at 12:55
  • Can you please mention your android version. – Jitesh Mohite Jul 08 '18 at 15:43
  • @jiteshmohite It is Android 7,0 (Nougat). – Usman Rana Jul 09 '18 at 07:02
  • @Ibrahim i'm setting elevation to my view like this : android:elevation="3dp" – Usman Rana Jul 09 '18 at 07:05
  • Elevation graphics is added around the view, and is not strictly part of it. If you want to grab the elevation graphic, you need to wrap the view inside another view and then generate a bitmap from that. Make sure the container view has enough padding to properly contain the view's shadow. Even with clipping disabled, I don't think drawing onto a bitmap will draw outside of the view's bounds. – Gil Moshayof Jul 10 '18 at 10:17

1 Answers1

6
public static Bitmap generateBitmap(Context context, String msg) {
        Bitmap bitmap = null;
        LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //Inflate the layout into a view and configure it the way you like
        RelativeLayout view = new RelativeLayout(context);
        try {
            mInflater.inflate(R.layout.point_helper, view, true);
        } catch (Exception e) {
            e.printStackTrace();
        }

        TextView tv = (TextView) view.findViewById(R.id.textView);
        tv.setText(msg);

        //Provide it with a layout params. It should necessarily be wrapping the
        //content as we not really going to have a parent for it.
        view.setLayoutParams(new ViewGroup.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT));

        //Pre-measure the view so that height and width don't remain null.
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

        //Assign a size and position to the view and all of its descendants
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

        //Create the bitmap
        bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

        //Create a canvas with the specified bitmap to draw into
        Canvas c = new Canvas(bitmap);

        //Render this view (and all of its children) to the given Canvas
        view.draw(c);

        return bitmap;
    }

Drawable for layout background, put it inside drawable folder and set it.

bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <layer-list>
            <item>
                <shape>
                    <solid android:color="#35000000" />
                    <corners android:radius="2dp" />
                </shape>
            </item>
            <item android:bottom="3dp" android:left="1dp" android:right="3dp" android:top="1dp">
                <shape>
                    <solid android:color="#ffffff" />
                    <corners android:radius="1dp" />
                </shape>
            </item>
        </layer-list>
    </item>
</selector>

I slightly modified your logic, Have a look at this code. It requires a layout. If layout is not possible to provide, try to give the parent view of the bitmap view.

Ranjan
  • 1,326
  • 18
  • 38
  • 1
    If we took an example of a card-view with elevation/shadow, this will not solve the issue and the bitmap will appear without the shadow/elevation which is hardware accelerated. – Mohamed Zakaria El-Zoghbi Jul 09 '18 at 14:49
  • 2
    can you please highlight the part of code that will make the output different than my code? It seems you are doing same thing, i'm setting layout text etc and then passing view to this method, and you are doing that inside the method. – Usman Rana Jul 10 '18 at 06:20
  • your and my generation method are are different for bitmap generation. You can use the drawable, may be it solves your problem. – Ranjan Jul 10 '18 at 06:32
  • My view has ImageView and TextView, and only ImageView has shadow – Usman Rana Jul 10 '18 at 09:35
  • That's why, I provided you different type of method for generating bitmap. Or use drawable in parent view. It's simple – Ranjan Jul 10 '18 at 09:54
  • It is a good hack to show custom drawable as shadow and i'm already using that, but it is not exactly like default shadow. I want to look for a method with which default elevation property can work. – Usman Rana Jul 11 '18 at 06:03
  • you can later add shadow to Imageview. If you want 100% exactly – Ranjan Jul 11 '18 at 06:04