方向改变后,小部件上的按钮无响应。

11

我在一个小部件上有两个按钮,可以更改小部件中的一些项目。如果在手机上更改了方向,则这些按钮将无效。我阅读过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);
}

我假设您指的是一个应用小部件。您应该澄清这一点,因为UI小部件(例如按钮)和应用小部件之间可能会存在混淆。 - Rich Schuler
你能否在你的AppWidget提供程序中发布onUpdate()方法的代码? - Rich Schuler
在屏幕方向改变后,我检查了一下,发现onUpdate没有被调用。 - dfilkovi
其他的小部件能正常工作吗?这可能是你所使用的主屏幕启动器出了问题。 - Moncader
你能发一些代码吗?你是如何将onClick监听器添加到按钮上的? - Jason Knight
添加了整个 onUpdate 函数。 - dfilkovi
4个回答

13

我建议创建一个服务(Service),可能是在你的AppWidgetProvider中进行子类化,并重写onConfigurationChanged()方法。使用服务可以将业务逻辑委托给服务处理,构建和更新你的小部件。它还可以让你管理旋转。如果你正在执行任何阻塞操作,那么服务将是一个好地方来启动一个线程,并将结果返回到主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

此外,请确保在清单文件中指定您对旋转更改通知感兴趣。类似以下内容即可: android:configChanges="keyboardHidden|orientation" 在清单文件中的服务声明中声明。

希望这可以帮到您!


1
onConfigurationChanged方法中的代码毫无意义。你的oldOrientation值将始终是newConfig所具有的方向值,因为在方向实际更改后读取当前配置。但是,检测小部件方向变化的想法值得肯定。 - Mike

2
无论是使用Activity还是Broadcast Receiver(应用程序小部件提供程序),只要更新小部件的外观,就必须重新分配所有点击处理程序的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);
}

0

如果你使用

RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

要更改远程视图对象内特定视图的某些状态,您需要同时更改其他视图,因为方向更改事件仅会记住您用于更新小部件的最后一个RemoteViews对象。它将使用该最后使用的RemoteViews对象重新创建小部件。这就是为什么您始终需要更新RemoteViews对象中的所有视图以及所有视图的侦听器。

其余部分将由操作系统自动处理。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接