简体   繁体   English

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

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

I am writing a home screen widget and want to update the home screen widget when the device orientation changes from portrait to landscape or the other way.我正在编写一个主屏幕小部件,并希望在设备方向从纵向变为横向或其他方式时更新主屏幕小部件。 How can I make it?我怎样才能做到?

Currently, I tried to reigster to CONFIGURATION_CHANGED action like the code below, but the Android didn't allow me to do that by saying "IntentReceiver components are not allowed to register to receive intents".目前,我尝试像下面的代码一样重新注册 CONFIGURATION_CHANGED 操作,但 Android 不允许我这样做,说“IntentReceiver 组件不允许注册以接收意图”。 Can someone help me?有人能帮我吗? Thanks.谢谢。

public class MyWidget extends AppWidgetProvider {

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

I know it's an old question but there's indeed an easier way to do this than delegating the update to an IntentService.我知道这是一个老问题,但确实有比将更新委托给 IntentService 更简单的方法。 The way to deal with orientation changes is to listen for configuration changes in the Application and broadcast an ACTION_APPWIDGET_UPDATE to the widget.处理方向更改的方法是侦听应用程序中的配置更改并向小部件广播 ACTION_APPWIDGET_UPDATE。

Add an Application class to your app向您的应用程序添加一个 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);
    }
}

The method will be called whenever a configuration change occurs, one of them being an orientation change.每当发生配置更改时都会调用该方法,其中之一是方向更改。 You could improve the method by doing the broadcast only when it's an orientation change and not eg a change of the system language.您可以通过仅在方向更改而不是例如系统语言更改时进行广播来改进方法。 The method basically sends an update broadcast to all instances of your widget.该方法基本上向小部件的所有实例发送更新广播。

Define the MyApplication in your manifest在清单中定义 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>

You probably shouldn't need to do this.您可能不需要这样做。 You can use layout and layout-land folders to provide different layouts in each orientation via xml without manually detecting rotation.您可以使用 layout 和 layout-land 文件夹通过 xml 在每个方向提供不同的布局,而无需手动检测旋转。 However, you shouldn't do anything functionally different in each orientation as a lot of devices can't rotate the homescreen and whatever features you put in will be inaccessible for them.但是,您不应该在每个方向上做任何功能上不同的事情,因为许多设备无法旋转主屏幕,并且您放置的任何功能对它们来说都将无法访问。

While I sorta agree with jqpubliq's answer, so long as you think about what you're doing and design matters properly, you are welcome to implement different layouts for different orientations.虽然我有点同意 jqpubliq 的回答,但只要您考虑自己在做什么并且设计很重要,欢迎您为不同的方向实现不同的布局。 It's just going to be complicated.只是会很复杂。

The error message you received should be self-explanatory: BroadcastReceivers (like AppWidgetProvider ) cannot register for other broadcasts.您收到的错误消息应该是不言自明的: BroadcastReceivers (如AppWidgetProvider )无法注册其他广播。 After all, a manifest-registered BroadcastReceiver instance should be in memory for milliseconds, not forever.毕竟,清单注册的BroadcastReceiver实例应该在内存中保留几毫秒,而不是永远。

Hence, to implement this logic, you will need to:因此,要实现此逻辑,您需要:

  1. Create an IntentService that handles the actual app widget updates, and have your AppWidgetProvider delegate its work to that.创建一个处理实际应用小部件更新的IntentService ,并让您的AppWidgetProvider将其工作委托给它。 Here is an example . 这是一个例子
  2. Create a separate BroadcastReceiver implementation, registered in the manifest to receive CONFIGURATION_CHANGED broadcast Intents .创建一个单独的BroadcastReceiver实现,在清单中注册以接收CONFIGURATION_CHANGED广播Intents
  3. Have that new BroadcastReceiver also use the IntentService (eg, call startService() ).让新的BroadcastReceiver也使用IntentService (例如,调用startService() )。
  4. Have IntentService handle the updates for both orientations, emanating from both receivers.IntentService处理来自两个接收器的两个方向的更新。

On Android 3.x and above, who has RemoteViewsService, can be used在Android 3.x及以上,有RemoteViewsService的,可以使用

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

in RemoteViewsService childs.在 RemoteViewsService 子项中。 If widget will not be updated, widget UI can be cleaned or just hangs and stop react on external events.如果小部件不会更新,小部件 UI 可以被清理或只是挂起并停止对外部事件的反应。

Since Android API 16, there is a new override that receives information about widget options changes, mainly min/max width/height.从 Android API 16 开始,有一个新的覆盖可以接收有关小部件选项更改的信息,主要是最小/最大宽度/高度。

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

When this is called, one can check current device orientation and update widgets appropriately, or "simply" call the onUpdate() method which will have to get orientation information.当它被调用时,可以检查当前设备方向并适当地更新小部件,或者“简单地”调用必须获取方向信息的 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 });
}

The onUpdate() can do something like this: 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