Search code examples
javaandroidandroid-studiowidgetremoteview

Programmatically set a percentage height to LinearLayout in a Widget's RemoteViews


I want to create a widget with graphs which represent a percentage increase in stock value for certain assets. I was able to create an overview of graphs with each graph having a percentage height by putting two LinearLayouts in a container LinearLayout. The bottom LinearLayout is the graph and the top LinearLayout is the spacer which gets a certain layout_weight. This way I can reduce the size of the other container using percentages. (if the spacer has a layout_weight of 0.4, then the graph is 60% high).

The current state of the widget is (I wanted to handle negative values in red afterwards, but no need to continue if I can't figure out how to percentually size the graphs) :

An example of the current state of the widget.

I chose this approach because I can't use ConstraintLayout in RemoteViews. Everything seemed to work nicely, but when I wanted to programmatically change the size of the spacer based on data from the api (so the sizes of the graphs truly match the percentage increase of the stock value), I wasn't able to. There is, as far as I could see, no way to change the layout_weight of a LinearLayout in a RemoteView in java.

I then thought maybe my last hope would be to find the container - which contains all the graphs - its height by using findViewById, but that's also not possible with RemoteViews. I then would've seen the container's height as 100% and then set the height of the other LinearLayouts according to that size. 60% would be 0.6 times the height I fetched from the container. But that, I'm afraid, is also not possible.

So I actually have no clue how to programmatically find out how high a LinearLayout is or how I can change the size of a LinearLayout percentually. It seems like I always already need to know the sizes of the containers which will be used in the widget? Which is kind of annoying as the content varies and it needs to be rendered differently based on the ratio of each gain of each asset.

Am I missing a certain way to approach this? I can't seem to find much more on the Android Developers documentation... Cheers!


Solution

  • The ability to affect things like that was only added in API Level 31 (Android 12), with methods like setViewLayoutHeight(). So, one option would be to set your minSdk to be 31 and live with a smaller user base for a while.

    Or:

    • For a complex UI, you might consider rendering a Bitmap inside your app, then showing that Bitmap in an ImageView in the app widget (with the Bitmap served via a ContentProvider). This is annoying, but it gives you ultimate flexibility.

    • Another possibility is to have a bunch of different layout resources, where you encode a range of desired weights, the use the desired one in the RemoteViews when you go to update it. If you keep consistent widget IDs, the rest of your code should not need to change much.

    • You have the question tagged as . If you eventually learn Kotlin, you could see if Glance has some more flexibility. Glance uses Jetpack Compose to create app widgets (and Wear OS tiles).