我在窗口小部件上有两个按钮可以更改窗口小部件中的某些项目,如果在手机上更改了方向,则按钮不执行任何操作。我读了http://developer.android.com/guide/topics/resources/runtime-changes.html但这都是关于活动而不是小部件。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent active = new Intent(context, TvWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
mDbHelper = new DbAdapter(context);
fillChannelList(context, appWidgetIds[appWidgetIds.length-1]);
Set<Integer> keys = channelsImages.keySet();
Iterator<Integer> iter = keys.iterator();
while(iter.hasNext())
{
if(channelId == 0)
{
channelId = iter.next();
break;
}
}
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
Editor edit = settings.edit();
edit.putInt("channelId", channelId);
edit.putInt("appWidgetIds", appWidgetIds[appWidgetIds.length-1]);
edit.commit();
active.putExtra("net.aerosoftware.tvvodic.appWidgetIds", appWidgetIds);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.button_next, actionPendingIntent);
Intent refresh = new Intent(context, TvWidget.class);
refresh.setAction(ACTION_WIDGET_REFRESH);
refresh.putExtra("net.aerosoftware.tvvodic.appWidgetIds", appWidgetIds);
PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0, refresh, 0);
remoteViews.setOnClickPendingIntent(R.id.button_refresh, refreshPendingIntent);
updateView(context);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
答案 0 :(得分:12)
我建议创建一个Service(可能在AppWidgetProvider中继承它)并覆盖onConfigurationChanged()方法。使用该服务将允许您委派业务逻辑以由服务处理,构建和更新窗口小部件。它还允许您管理旋转。如果您正在执行任何阻塞操作,那么该服务将是一个产生Thread并将结果返回到主UI线程以避免ANR的好地方。
我建议如下:
public class MyWidget extends AppWidgetProvider
{
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
context.startService(new Intent(context, MyUpdateService.class));
}
public static class MyUpdateService extends Service
{
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
// Update the widget
RemoteView remoteView = buildRemoteView(this);
// Push update to homescreen
pushUpdate(remoteView);
// No more updates so stop the service and free resources
stopSelf();
}
public RemoteViews buildRemoteView(Context context)
{
RemoteView updateView = null;
updateView = new RemoteViews(context.getPackageName(), R.layout.my_widget_layout);
// Your code to build and update the remote view
return updateView;
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
int oldOrientation = this.getResources().getConfiguration().orientation;
if(newConfig.orientation != oldOrientation)
{
// Update the widget
RemoteView remoteView = buildRemoteView(this);
// Push update to homescreen
pushUpdate(remoteView);
}
}
private void pushUpdate(RemoteView remoteView)
{
ComponentName myWidget = new ComponentName(this, MyWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(myWidget, updateViews);
}
}
}
另请查看此链接:http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html
此外,请务必表明您有兴趣在清单中接收有关轮换更改的通知。这样的东西会起作用: 机器人:configChanges = “keyboardHidden |方向” 在清单中的服务声明中声明。
希望有所帮助!
答案 1 :(得分:2)
每当您更新窗口小部件的外观(使用活动或广播接收器[应用小部件提供商])时,您还必须为点击处理程序重新分配所有PendingIntents,然后正常调用updateAppWidget()
。
setTextViewText()
的示例:
// This will update the Widget, but cause it to
// stop working after an orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
// This is the correct way to update the Widget,
// so that it works after orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
Intent intent = new Intent(context, MyWidgetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, ...);
remoteViews.setOnClickPendingIntent(R.id.widget_click_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
答案 2 :(得分:0)
问题可能是由于Widget上有两个按钮,这会导致问题。见这里:
http://permalink.gmane.org/gmane.comp.handhelds.android.devel/98008
或
但目前尚不清楚真正的解决方案是什么(不需要创建后台服务的解决方案)。
答案 3 :(得分:0)
如果您使用
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
要更改远程视图对象内部特定视图的某些状态,您还需要更改其他视图,因为方向更改事件将仅记住您用于更新窗口小部件的最后一个RemoteViews对象。它将使用上次使用的RemoteViews对象重新创建窗口小部件。这就是为什么您总是需要更新RemoteViews对象内的所有视图,以及视图的所有侦听器。
其余部分将由操作系统自动处理。