如何在主屏幕小部件中检测方向变化?

时间:2010-03-12 20:10:12

标签: android

我正在编写主屏幕小部件,并希望在设备方向从纵向更改为横向或其他方式时更新主屏幕小部件。我该怎么做?

目前,我尝试像下面的代码一样重新配置CONFIGURATION_CHANGED操作,但Android不允许我这样说“不允许IntentReceiver组件注册接收意图”。有人能帮我吗?感谢。

public class MyWidget extends AppWidgetProvider {

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
        this.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
    }

5 个答案:

答案 0 :(得分:8)

我知道这是一个古老的问题,但确实比将更新委派给IntentService更容易。 处理方向更改的方法是在应用程序中侦听配置更改,并向窗口小部件广播ACTION_APPWIDGET_UPDATE。

将应用类添加到您的应用

public class MyApplication extends Application {

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // create intent to update all instances of the widget
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class);

        // retrieve all appWidgetIds for the widget & put it into the Intent
        AppWidgetManager appWidgetMgr = AppWidgetManager.getInstance(this);
        ComponentName cm = new ComponentName(this, MyWidget.class);
        int[] appWidgetIds = appWidgetMgr.getAppWidgetIds(cm);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);

        // update the widget
        sendBroadcast(intent);
    }
}

只要发生配置更改,就会调用该方法,其中一个是方向更改。您可以通过仅在广播方向改变时进行广播来改进该方法,而不是例如改变系统语言。 该方法基本上向您的小部件的所有实例发送更新广播。

在清单中定义MyApplication

<application
    android:name="yourpackagename.MyApplication"
    android:description="@string/app_name"
    android:label="@string/app_name"
    android:icon="@drawable/app_icon">

    <!-- here go your Activity definitions -->

</application>

答案 1 :(得分:3)

你可能不需要这样做。您可以使用layout和layout-land文件夹通过xml在每个方向上提供不同的布局,而无需手动检测旋转。但是,您不应该在每个方向上做任何功能上不同的事情,因为许多设备无法旋转主屏幕,并且您输入的任何功能都将无法访问。

答案 2 :(得分:2)

虽然我很同意jqpubliq的回答,但只要你想到你正在做什么和设计是否正确,你就可以为不同的方向实现不同的布局。它会变得复杂。

您收到的错误消息应该是不言自明的:BroadcastReceivers(如AppWidgetProvider)无法注册其他广播。毕竟,一个清单注册的BroadcastReceiver实例应该在内存中存在毫秒,而不是永远。

因此,要实现此逻辑,您需要:

  1. 创建一个处理实际应用小部件更新的IntentService,让您的AppWidgetProvider委托其工作。 Here is an example
  2. 创建单独的BroadcastReceiver实施,在清单中注册以接收CONFIGURATION_CHANGED广播Intents
  3. 让新的BroadcastReceiver也使用IntentService(例如,致电startService())。
  4. IntentService处理两个方向的更新,从两个接收器发出。

答案 3 :(得分:1)

在Android 3.x及更高版本上,可以使用具有RemoteViewsService的人

@Override
public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(newConfig);
   //call widget update methods/services/broadcasts 
}
RemoteViewsService子项中的

。 如果窗口小部件不会更新,则可以清除窗口小部件UI,或者只是挂起并停止对外部事件做出反应。

答案 4 :(得分:0)

自Android API 16起,有一个新的替代项可以接收有关小部件选项更改的信息,主要是最小/最大宽度/高度。

@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)

调用此方法时,可以检查当前设备的方向并适当地更新小部件,或者“简单地”调用onUpdate()方法,该方法将必须获取方向信息。

@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
{
    int width = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
    int height = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
    int orientation = context.getResources().getConfiguration().orientation;

    if (BuildConfig.DEBUG) logWidgetEvents("UPDATE " + width + "x" + height + " - " + orientation, new int[] { appWidgetId }, appWidgetManager);

    onUpdate(context, appWidgetManager, new int[] { appWidgetId });
}

onUpdate()可以执行以下操作:

int rotation = context.getResources().getConfiguration().orientation;
if (rotation == Configuration.ORIENTATION_PORTRAIT)
{
    ... portrait ...
}
else
{
    ... landscape ...
}