1

I want to place 4 bitmaps in a large notification icon. Each bitmap should be placed in one quarter of the icon.

I've created a layout "notification_large_icon_layout.xml" for the icon:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/notification_large_icon_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/thumbnail1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_contact_picture" />

    <ImageView
        android:id="@+id/thumbnail2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignRight="@+id/thumbnail1"
        android:src="@drawable/ic_contact_picture" />

    <ImageView
        android:id="@+id/thumbnail3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/thumbnail1"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:src="@drawable/ic_contact_picture" />

    <ImageView
        android:id="@+id/thumbnail4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/thumbnail2"
        android:layout_alignRight="@+id/thumbnail3"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_contact_picture" />

</RelativeLayout>

And I have added the following code into my notification function:

...
// Create bitmap and scale it to 1/2
Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(rowUri));
Resources res = getApplicationContext().getResources();
int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);
bitmap = Bitmap.createScaledBitmap(bitmap, width/2, height/2, false);

// Inflate the layout for the large icon                            
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.notification_large_icon_layout, null);

// Copy bitmap to the 4 views
ImageView thumbnailView = (ImageView) view.findViewById(R.id.thumbnail1);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail3);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail4);
thumbnailView.setImageBitmap(bitmap);

// Convert view to bitmap
Bitmap icon = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
view.draw(canvas);

notificationBuilder.setLargeIcon(icon);
...

It doesn't work. The icon is only gray.

Change 1:

I've changed the layout as follows (less flexible):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/notification_large_icon_layout"
    android:layout_width="128dp"
    android:layout_height="128dp" >

    <ImageView
        android:id="@+id/thumbnail1"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />

    <ImageView
        android:id="@+id/thumbnail2"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/thumbnail1" />

    <ImageView
        android:id="@+id/thumbnail3"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/thumbnail1" />

    <ImageView
        android:id="@+id/thumbnail4"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/thumbnail2"
        android:layout_toRightOf="@+id/thumbnail3" />

</RelativeLayout>

And I've changed the function like this:

...
// Create bitmap and scale it to 1/2
Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(rowUri));
Resources res = getApplicationContext().getResources();
int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);
bitmap = Bitmap.createScaledBitmap(bitmap, width/2, height/2, false);

// Inflate the layout for the large icon                            
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.notification_large_icon_layout, null);

view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); 

// Copy bitmap to the 4 views
ImageView thumbnailView = (ImageView) view.findViewById(R.id.thumbnail1);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail3);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail4);
thumbnailView.setImageBitmap(bitmap);

// Convert view to bitmap
Bitmap icon = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
view.draw(canvas);

notificationBuilder.setLargeIcon(icon);
...

Now I can see 1 bitmap with half resolution/density. Seems like the 4 bitmaps are overlapped.

Change 2:

The following code works:

...
// Create bitmap and scale it to 1/2
Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(rowUri));
Resources res = getApplicationContext().getResources();
int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);
bitmap = Bitmap.createScaledBitmap(bitmap, width/2, height/2, false);

// Inflate the layout for the large icon
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.notification_large_icon_layout, null);
view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); 

// Copy bitmap to the 4 views
ImageView thumbnailView = (ImageView) view.findViewById(R.id.thumbnail1);
thumbnailView.setBottom(height/2);
thumbnailView.setRight(width/2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail2);
thumbnailView.setBottom(height/2);
thumbnailView.setLeft(width/2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail3);
thumbnailView.setTop(height/2);
thumbnailView.setRight(width/2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail4);
thumbnailView.setTop(height/2);
thumbnailView.setLeft(width/2);
thumbnailView.setImageBitmap(bitmap);

// Convert view to bitmap
Bitmap icon = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
view.draw(canvas);

notificationBuilder.setLargeIcon(icon);
...

But I wonder, why I have to explicitly define the positions of the bitmaps.

Btw: The following snippets A and B have the same result. I can't see any difference.

Snippet A:

Bitmap icon = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
view.draw(canvas);

Snippet B:

view.setDrawingCacheEnabled(true);
Bitmap icon = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
samo
  • 373
  • 3
  • 8
  • 23
  • Could you try to use relative placement for your icons ? – Snicolas Aug 18 '13 at 15:34
  • Don't reinvent the wheel, use Photoshop – Maxim Shoustin Aug 18 '13 at 15:36
  • @MaximShoustin This is only an example. Finally I want to place 4 different bitmaps, which will be determined during runtime. That's why Photoshop is no solution. – samo Aug 18 '13 at 15:43
  • @Snicolas What do you mean exactly? I'm already using RelativeLayout – samo Aug 18 '13 at 15:45
  • android:toRightOf, android:toLeftOf, android:above, android:below... You actually don't take into account (at all) the size of each image to place others. They will overlap. – Snicolas Aug 18 '13 at 15:51
  • I've changed the layout and code – samo Aug 18 '13 at 18:22
  • 1
    Had you tried something like this [http://pastebin.com/Z0AkMUrA](http://pastebin.com/Z0AkMUrA)?. If you have your bitmaps in R.drawables can use `BitmapFactory.decodeResource(res, id)` then to get the bitmap from the canvas, well here is an explanetion of how do it: [Conver view into bitmap](http://stackoverflow.com/questions/4264990/convert-view-into-bitmap) – 4gus71n Aug 19 '13 at 01:37
  • @astinx Thanks for your help. When I explicitly define the position of the bitmaps it works. Why this is necessary? Is there are way to correctly inflate the layout from the xml file? – samo Aug 19 '13 at 19:58
  • @samo I really don't know, that code is from some old app that I developed. Android is pretty messy with the bitmaps, you can see that when you don't have any method to turn a canvas into a bitmap or viceversa... – 4gus71n Aug 19 '13 at 22:32

1 Answers1

0

I've found my mistake. The icon referenced by the attribute android:src of the ImageView had the wrong size. After changing the size to 64 x 64 the layout could be correctly inflated:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notification_large_icon_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

<ImageView
    android:id="@+id/thumbnail1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_icon" />

<ImageView
    android:id="@+id/thumbnail2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/thumbnail1"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_icon" />

<ImageView
    android:id="@+id/thumbnail3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/thumbnail1"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_icon" />

<ImageView
    android:id="@+id/thumbnail4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/thumbnail2"
    android:layout_toRightOf="@+id/thumbnail3"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_icon" />

</RelativeLayout>

My source looks now like this:

...
Resources res = getApplicationContext().getResources();
int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);

// Inflate the layout for the large icon
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.notification_large_icon_layout, null);
view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

// Copy bitmap to the 4 views                           
Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(rowUri));
ImageView thumbnailView = (ImageView) view.findViewById(R.id.thumbnail1);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail2);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail3);
thumbnailView.setImageBitmap(bitmap);
thumbnailView = (ImageView) view.findViewById(R.id.thumbnail4);
thumbnailView.setImageBitmap(bitmap);

// Convert view to bitmap
Bitmap icon = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(icon);
view.draw(canvas);

notificationBuilder.setLargeIcon(icon);
...
samo
  • 373
  • 3
  • 8
  • 23