Reputation: 3538
Android design pattern guide says widget's content and layout can be dynamically adjusted to the size the user defined through resize operation here: Design guide for widgets
Example provided in the design guide:
But I do not see anything in the docs as to how to accomplish this. How do we change the layout as per resize operation? Any ideas regarding the approach will be appreciated.
Upvotes: 36
Views: 16377
Reputation: 739
Based on Gogu response and according this answer about how to get widget size, I'm created this WidgetClass
in Kotlin
:
class WidgetClass: AppWidgetProvider() {
override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {
for (id in appWidgetIds!!) {
//get widget options for later get widget dimensions
val options = appWidgetManager?.getAppWidgetOptions(id)
//get widget view based on widget size
val view = getView(context, options)
//update widget
appWidgetManager!!.updateAppWidget(id, view)
}
}
//listen for widget changes
override fun onAppWidgetOptionsChanged(context: Context?, appWidgetManager: AppWidgetManager?,
appWidgetId: Int, newOptions: Bundle?) {
//update widget view based on new options
appWidgetManager?.updateAppWidget(appWidgetId, getView(context, newOptions))
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
}
private fun getView(context: Context?, options: Bundle?): RemoteViews {
val minWidth: Int
val minHeight: Int
if (context!!.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|| context.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) {
minWidth = options?.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) ?: 0
minHeight = options?.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT) ?: 0
} else {
minWidth = options?.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) ?: 0
minHeight = options?.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) ?: 0
}
//get widget view accordin widget size
return if (minWidth >= 240)
RemoteViews(context.packageName, R.layout.widget_large)
else
RemoteViews(context.packageName, R.layout.widget_small)
}
}
Upvotes: 1
Reputation: 6080
@Choletski @azendh
After changing layouts some click events are not called anymore
I solved this problem by creating function that setOnClickPendingIntent on view, and then return it.
For example the code is like
private RemoteViews getConfiguredView (RemoteViews remoteViews, Context context){
Intent refreshIntent = new Intent(context, EarningsWidget.class);
refreshIntent.setAction(REFRESH_ACTION);
PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 3, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.refreshButton, toastPendingIntent);
return remoteViews;
}
And than function is called where you do "Get appropriate remote view."
return getConfiguredView(new RemoteViews(context.getPackageName(), R.layout.activity_widget), context);
Upvotes: 0
Reputation: 3538
Thanks to A--C , this is possible for Jellybean and above devices and is simple to implement.
Below is the sample code using onAppWidgetOptionsChanged
method
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onAppWidgetOptionsChanged(Context context,
AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
Log.d(DEBUG_TAG, "Changed dimensions");
// See the dimensions and
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
// Get min width and height.
int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
int minHeight = options
.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
// Obtain appropriate widget and update it.
appWidgetManager.updateAppWidget(appWidgetId,
getRemoteViews(context, minWidth, minHeight));
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId,
newOptions);
}
/**
* Determine appropriate view based on width provided.
*
* @param minWidth
* @param minHeight
* @return
*/
private RemoteViews getRemoteViews(Context context, int minWidth,
int minHeight) {
// First find out rows and columns based on width provided.
int rows = getCellsForSize(minHeight);
int columns = getCellsForSize(minWidth);
if (columns == 4) {
// Get 4 column widget remote view and return
} else {
// Get appropriate remote view.
return new RemoteViews(context.getPackageName(),
R.layout.quick_add_widget_3_1);
}
}
/**
* Returns number of cells needed for given size of the widget.
*
* @param size Widget size in dp.
* @return Size in number of cells.
*/
private static int getCellsForSize(int size) {
int n = 2;
while (70 * n - 30 < size) {
++n;
}
return n - 1;
}
Upvotes: 35