繁体   English   中英

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

[英]How to detect orientation change in home screen widget?

我正在编写一个主屏幕小部件,并希望在设备方向从纵向变为横向或其他方式时更新主屏幕小部件。 我怎样才能做到?

目前,我尝试像下面的代码一样重新注册 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));
    }

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

向您的应用程序添加一个 Application 类

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>

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

虽然我有点同意 jqpubliq 的回答,但只要您考虑自己在做什么并且设计很重要,欢迎您为不同的方向实现不同的布局。 只是会很复杂。

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

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

  1. 创建一个处理实际应用小部件更新的IntentService ,并让您的AppWidgetProvider将其工作委托给它。 这是一个例子
  2. 创建一个单独的BroadcastReceiver实现,在清单中注册以接收CONFIGURATION_CHANGED广播Intents
  3. 让新的BroadcastReceiver也使用IntentService (例如,调用startService() )。
  4. IntentService处理来自两个接收器的两个方向的更新。

在Android 3.x及以上,有RemoteViewsService的,可以使用

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

在 RemoteViewsService 子项中。 如果小部件不会更新,小部件 UI 可以被清理或只是挂起并停止对外部事件的反应。

从 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 ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM