While OPTION_APPWIDGET_MIN/MAX_WIDTH/HEIGHT does not really report real values, I have found a way around it. Note that this does not really solve the problem, but is a rather confusing workaround.
Source of idea
Normal update from the widget host 26061-26061/net.twisterrob.app.debug V/TAG﹕ onReceive(Intent { act=android.appwidget.action.APPWIDGET_UPDATE flg=0x10000010 cmp=net.twisterrob.app.debug/net.twisterrob.app.AppWidgetProvider (has extras) } (Bundle[{appWidgetIds=[ I@42b14090 }])) 26061-26061/net.twisterrob.app.debug V/TAG﹕ onUpdate([483]) User tap with setOnClickPendingIntent 26061-26061/net.twisterrob.app.debug V/TAG﹕ onReceive(Intent { act=android.appwidget.action.APPWIDGET_UPDATE flg=0x10000010 cmp=net.twisterrob.app.debug/net.twisterrob.app.AppWidgetProvider bnds=[281,756][533,1071] (has extras) } (Bundle[{appWidgetIds=[ I@42b14090 }])) 26061-26061/net.twisterrob.app.debug V/TAG﹕ onUpdate([483])
Study
When RemoteViews.setOnClickPendingIntent broadcasts the faucet by the user, it will place the view boundaries in the Intent . As you can see in bnds=[281,756][533,1071] , the views 533-281=252 wide and 1071-756=315 tall are pixels, and Galaxy S4 is a XXHDPI (3x) device, so 252x315 / 3 = 84x105 , which was my empirical observation about the size of widget cells.
The specified boundaries depend on the viewId specified by setOnClickPendingIntent , so to get the size of the cell, you need to attach the pending intent to the root view in the layout. My widget has a tap-to-refresh listener that I can safely attach to the root layout. There are other views that have PendingIntent s, but they span the root layout, so their intent will be translated as normal onClickListener s.
Decision
Now this means that we know the exact size of the cell, based on this it will be possible to calculate the size of individual views (for simpler layouts). Essentially, we have a way to get root.getHeight() , we can "hard code" the size of first in R.dimen.firstHeight , and from this we can calculate whether to show first , second or not.
Or use these borders just like @AndrewOrobator suggested: inflate the layout to fit the size.
User interaction required
The only problem that requires user interaction at least once. When the widget host sends an update, there are no restrictions, so the user must click on the view so that we have the size. I would wrap this around, forcing the user to click on the view once (immediately after installing the widget on the house):
@Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction())) { for (int appWidgetId : getAppWidgetIds(intent)) { Rect storedBounds = getSizeFromPreferences(appWidgetId); Rect sourceBounds = intent.getSourceBounds(); if (storedBounds == null && sourceBounds != null) {