【问题标题】:Detect rotation of Android home screen检测Android主屏幕的旋转
【发布时间】:2015-09-02 13:18:39
【问题描述】:

我有一个App Widget,当它更新时,它会获取一个尺寸与小部件匹配的图像,并将该图像放入ImageView(通过RemoteViews)。它工作得很好。

但对于支持主屏幕旋转的设备(我不是在谈论基于设备方向的Activity 的旋转,而是关于主屏幕的旋转 本身)小部件的尺寸和纵横比在从横向变为纵向时会发生一些变化,反之亦然......即不保持固定大小。

因此,我的小部件需要能够检测主屏幕何时旋转,并获取新图像(或至少加载不同的预取图像)。

我终其一生都无法弄清楚这是否可行以及如何可行。有什么线索吗?

【问题讨论】:

标签: android rotation android-appwidget homescreen


【解决方案1】:

使用以下代码检测方向:-

    View view = getWindow().getDecorView();
    int orientation = getResources().getConfiguration().orientation;

    if (Configuration.ORIENTATION_LANDSCAPE == orientation) {
       relativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.log_landscape));
        imageview_Logo.setImageResource(R.drawable.log_landscape_2);
        Log.d("Landscape", String.valueOf(orientation));
        //Do SomeThing; // Landscape
    } else {
       relativeLayout.setBackgroundDrawable( getResources().getDrawable(R.drawable.login_bg) );
       imageview_Logo.setImageResource(R.drawable.logo_login);
        //Do SomeThing;  // Portrait
        Log.d("Portrait", String.valueOf(orientation));
    }

【讨论】:

    【解决方案2】:

    当当前设备配置(方向、语言环境等)发生变化时,您可以收听 android 系统发送的广播 ACTION_CONFIGURATION_CHANGED。 根据文档:

    ACTION_CONFIGURATION_CHANGED:

    广播动作:当前设备配置(方向, 语言环境等)已更改。当这种变化发生时,UI(视图 层次结构)将需要根据这些新信息进行重建;为了 大多数情况下,应用程序不需要担心这个,因为 系统将负责停止和重新启动应用程序 以确保它看到新的变化。一些系统代码不能 重新启动将需要注意此操作并处理它 适当的。

    您无法通过清单中声明的​​组件接收此信息,只能 通过使用 Context.registerReceiver() 显式注册它。

    这是一个受保护的意图,只能由系统发送。

    public class YourWidgetProvider extends AppWidgetProvider {
    
            @Override
            public void onEnabled(Context context) {
                super.onEnabled(context);
                context.registerReceiver(mOrientationChangeReceiver,new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
            }
    
            @Override
            public void onDisabled(Context context) {
                context.unregisterReceiver(mOrientationChangeReceiver);
                super.onDisabled(context);
            }
    
            public BroadcastReceiver mOrientationChangeReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent myIntent) {
                    if ( myIntent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                        if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
                            // landscape orientation
                            //write logic for building remote view here
                            // buildRemoteViews();
                        }
                        else {
                            //portrait orientation
                            //write logic for building remote view here
                            // buildRemoteViews();
                        }
                    }
                }
            };
        }
    

    【讨论】:

    • 提供者可能随时被销毁 - 在这种情况下,您的接收器会泄漏。据推测,稍后在 onDisabled 中,由于 mOrientationChangeReceiver 对于新的提供程序实例为空,它也会遇到 NPE。应用小部件是临时上下文,因此在这种情况下不适合注册接收器。
    【解决方案3】:

    从 Android API 16 开始,有一个接收配置信息的新覆盖。

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

    【讨论】:

      【解决方案4】:

      检查此代码是否有效:

       myButton.setOnClickListener(new OnClickListener() {
         public void onClick(View v) {
      
          int rotation = getWindowManager().getDefaultDisplay()
            .getRotation();
          // DisplayMetrics dm = new DisplayMetrics();
          // getWindowManager().getDefaultDisplay().getMetrics(dm);
          int orientation;
          CharSequence text;
      
          switch (rotation) {
          case Surface.ROTATION_0:
           text = "SCREEN_ORIENTATION_PORTRAIT";
           break;
          case Surface.ROTATION_90:
           text = "SCREEN_ORIENTATION_LANDSCAPE";
           break;
          case Surface.ROTATION_180:
           text = "SCREEN_ORIENTATION_REVERSE_PORTRAIT";
           break;
          case Surface.ROTATION_270:
           text = "SCREEN_ORIENTATION_REVERSE_LANDSCAPE";
           break;
          default:
           text = "SCREEN_ORIENTATION_PORTRAIT";
           break;
          }
      
          // CharSequence text = String.valueOf(orientation);
          Toast toast = Toast.makeText(getApplicationContext(), text,
            Toast.LENGTH_SHORT);
          toast.setGravity(Gravity.CENTER | Gravity.CENTER, 10, 0);
          toast.show();
      
         }
        });
      

      【讨论】:

      • 与为按钮设置 OnClickListener 的问题有什么关系?
      • 当我们实时旋转时,它会检测到 onclick 而不是 onconfiguration 更改,并重新启动活动。
      • 仅在以下情况下有效:主屏幕设置中允许屏幕旋转。
      【解决方案5】:

      使用Activity的onConfigurationChanged方法。见以下代码:

      @Override
      public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      
      // Checks the orientation of the screen
      if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
          Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
      } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
          Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
      }
      }
      

      好的,所以对于小部件,我们必须如下添加我们的应用程序类,并且不要忘记在清单中声明它,该方法基本上会向您的小部件的所有实例发送更新广播。

      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);
      }
      }
      

      在清单中...

      <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 -->
      

      【讨论】:

      • 问题是,我指的是 App Widget 而不是 Activity
      【解决方案6】:
      View view = getWindow().getDecorView();
      int orientation = getResources().getConfiguration().orientation;
      
      if (Configuration.ORIENTATION_LANDSCAPE == orientation) {
         relativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.log_landscape));
          imageview_Logo.setImageResource(R.drawable.log_landscape_2);
          Log.d("Landscape", String.valueOf(orientation));
          //Do SomeThing; // Landscape
      } else {
         relativeLayout.setBackgroundDrawable( getResources().getDrawable(R.drawable.login_bg) );
         imageview_Logo.setImageResource(R.drawable.logo_login);
          //Do SomeThing;  // Portrait
          Log.d("Portrait", String.valueOf(orientation));
      }
      

      【讨论】:

        【解决方案7】:

        您可以使用小部件的宽度和高度来检查它,如以下代码 sn-p 中所做的:

        WindowManager wm; 
        Display ds; 
        public boolean portrait; 
        
        public void checkOrientation() { 
            wm = getWindowManager(); 
            ds=wm.getDefaultDisplay(); 
        } 
        
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
        
            checkOrientation(); 
            if (ds.getWidth() > ds.getHeight()) { 
                // ---landscape mode--- 
                portrait = false; 
            } else if (ds.getWidth() < ds.getHeight()) { 
                // ---portrait mode--- 
                portrait = true; 
            } 
        } 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多