2

How to make a Material You-like widget with image whose corners are rounded?

It is already made in Google Photo, but how to get the same effect?

Many ways (like ShapeableImageView) are forbidden and impossible to bypass due to restrictions of RemoteView.

These are some additional details for the first suggested answer:

My widget.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/background"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/colorBackground"
    android:theme="@style/widget_theme">

    <ImageView
        android:id="@+id/widget_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/MY_IMAGE" />

</LinearLayout>

attrs.xml in res/values folder looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AppWidgetAttrs">
        <attr name="appWidgetPadding" format="dimension" />
        <attr name="appWidgetInnerRadius" format="dimension" />
        <attr name="appWidgetRadius" format="dimension" />
    </declare-styleable>
</resources>

styles.xml in res/values folder looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- Widget theme -->
    <style name="widget_theme" parent="Theme.Material3.DayNight">
        <item name="appWidgetRadius">@dimen/rounded_corners</item>
        <item name="appWidgetInnerRadius">@dimen/rounded_corners_inner</item>
        <item name="appWidgetPadding">0dp</item>
    </style>

</resources>

dimens.xml in res/values folder looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="rounded_corners">16dp</dimen>
    <dimen name="rounded_corners_inner">8dp</dimen>
</resources>

I test my app on a virtual Pixel 4a (API 30).

Minumum API is API 24.

Compile and Target SDKs are both API 31.

Vreny
  • 71
  • 7
  • Check this part from official document - https://developer.android.com/guide/topics/appwidgets#rounded-corner – Android Geek Jan 31 '22 at 03:56
  • @AndroidGeek I have already checked it for many times, but it still doesnt give me wanted result with **ImageView**. – Vreny Jan 31 '22 at 05:58
  • Check this medium post it may help you - https://medium.com/androiddevelopers/updating-your-widget-for-android-12-92e7de87424c – Android Geek Jan 31 '22 at 06:40
  • Unfortunately it didnt, so I think that Google used a separate method with use of some image processing library. Thanks anyway. – Vreny Jan 31 '22 at 07:38

2 Answers2

2

Actual solution

What the op wants is a widget containing only an image, and this image should be rounded, example:

Rounded corners image in widget

All you need is:

  • the widget layout, containing an imageview with your image. In the above example, i had (i used linear layout, but it depends on the desired final result):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/background"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/colorBackground"
    android:theme="@style/WidgetTheme">

    <ImageView
        android:id="@+id/test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/test" />

</LinearLayout>
  • A style for your widget, that's mine (supports the rounded corners and the automatic dark/light theme, even if in this particular widget the background color is not visibile)
    <!-- Widget theme -->
    <style name="WidgetTheme" parent="Theme.Material3.DayNight">
        <item name="appWidgetRadius">@dimen/rounded_corners</item>
        <item name="appWidgetInnerRadius">@dimen/rounded_corners_inner</item>
        <item name="appWidgetPadding">0dp</item>
    </style>
  • The above attributes must be declared as styleable in the attrs.xml file. Again, here's mine:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AppWidgetAttrs">
        <attr name="appWidgetPadding" format="dimension" />
        <attr name="appWidgetInnerRadius" format="dimension" />
        <attr name="appWidgetRadius" format="dimension" />
    </declare-styleable>
</resources>

That's all, if you want the image to be circular just set a huge border radius.

Old and misunderstood solution

I'm probably late, but i had the same problem. A simple workaround is to use a foreground to "mask" tha image form, when the image is a normal ImageView inside the widget's layout. So what i did was:

  1. Create this drawable, name it as you want
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M-0.1094,-0.0957L-0.1094,24.0957L24.1094,24.0957L24.1094,-0.0957L-0.1094,-0.0957zM12,0.123A11.8773,11.8773 0,0 1,23.877 12A11.8773,11.8773 0,0 1,12 23.877A11.8773,11.8773 0,0 1,0.123 12A11.8773,11.8773 0,0 1,12 0.123z"
          android:fillColor="#000"/>
    </vector>
  1. Use this drawable in your ImageView foreground and set its color to the background color (here i use the system background color, but use your color if it's different):
android:foreground="@drawable/ic_inverted_circle_foreground_black_24dp"
android:foregroundTint="?android:attr/colorBackground"
  1. Result:

Square image with inverse circle foreground

EDIT: the op request was different, but this remains a valid solution for images inside the layout of the widget, so i won't delete it, just in case.

m.i.n.a.r.
  • 922
  • 2
  • 12
  • 28
  • Personally I beleive that later is better than never, thank you. But you didnt quite understand the problem here. I want my image to cover **entire** shape of widget (as it is made in Google photos), there should be no buttons, no extra layers - just one image, that is covering entire space of shape. Ive already lost my hope in reaching Google`s secret here, so for me the best way to do that is cropping image at first and only then place it in *drawable* folder. – Vreny May 02 '22 at 09:40
  • Well, i'm sorry, i didn't understand. In such case, the rounded corners API should clip your image, if placed inside a linear layout, for example. I'm not 100% sure of this, but if it works with the background, it should work with everything inside too. And if not, you can always set the image as widget background in the root of the layout. I'll test both the solutions later :) – m.i.n.a.r. May 02 '22 at 10:46
  • 1
    Thanks again! Ill definetely check both of ways that you suggested. But if you have such option and time to, it will be also useful to hear your conclusions. – Vreny May 02 '22 at 19:11
  • Check the edited answer, i explained the first approach (both the solutions in the above comment work though) :) – m.i.n.a.r. May 03 '22 at 10:39
  • Enourmous thanks! It may sound dumb, but what are the *rounded_corners* and *rounded_corners_inner* in *dimens.xml/dimensions.xml* in your example picture (that one with flower on it)? I tried mixing different numbers in them, but the widget still doesnt have rounded corners. – Vreny May 04 '22 at 17:40
  • I use 16dp and 8dp respectively. If you still can't get it working, edit your question with additional details. And remember to mark my answer as accepted if it was useful! – m.i.n.a.r. May 04 '22 at 23:29
  • Tried those numbers, but the widget is still not affected in any way. You got my question right, but its pointless. Thank you again. *Some kind of curse, I guess.* – Vreny May 05 '22 at 13:48
  • 1
    That's clearly something missing. Please edit your answer with additional details. What Android version are you using to test? Is the layout of your widget the same of my example? Is the attrs.xml file in the correct folder? Don't give up, it's probably only a small oversight! I'm 100% sure the solution works. – m.i.n.a.r. May 06 '22 at 08:13
  • I have just updated my question with every possible thing that may affect the result. – Vreny May 06 '22 at 14:09
  • Sadly, there's nothing wrong with your code. I'll prepare a working demo project to attach to my answer later this week. In the meantime, i use the rounded corners API in one of my open source apps, take a look if you want, even if that's not exactly your case (but in your case the rounded corners API aren't working at all) https://github.com/m-i-n-a-r/birday/tree/develop – m.i.n.a.r. May 10 '22 at 09:44
  • To be honest, from the beginning I wanted to suggest you this way, but also thought about it as a last measure. Anyway, Im really looking forward for this demo and definetely will check your other project! – Vreny May 10 '22 at 18:19
0

Like everyone else I am also banging my head for past few weeks to get the rounded widget with image. I have only got I solution that works like char but it will only work on API 31 and above. Thats the sacrifice you have to according to me.

To get the rounded image in any widget just like this:

<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/flower"
    android:clipToOutline="true"
    android:background="@drawable/roundedcorner"/>

Here the key is to use

android:clipToOutline.

And drawable rounded corner is

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
  xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="25.0dip" />
    <solid android:color="@android:color/white" />
</shape>

Unfortunately this xml attribute will only work on API 31 and above. For android versions below that it will simply ignore the attribute and show the entire image without any rounded corners.

Rahul
  • 496
  • 4
  • 9