检测安卓主屏幕的旋转方向

24

我有一个App小部件,在更新时会获取与小部件相匹配的尺寸的图像,并将该图像放入ImageView(通过RemoteViews)。 它可以正常工作。

但是对于支持旋转主屏幕的设备(我说的不是基于设备方向旋转的例如Activity,而是主屏幕本身的旋转),当从横向切换到纵向或者反过来时,小部件的尺寸和宽高比会略微改变......也就是尺寸不能保持固定。

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

我无法弄清楚这是否可能以及如何实现。 有什么提示吗?


https://dev59.com/wkzSa4cB1Zd3GeqPnYmm - N Kaushik
感谢您给@andro_abc点踩,但我实际上没有看到在那个帖子中有效的答案。 - drmrbrewer
好的,我没有给它投反对票,可能是其他人 :) - N Kaushik
7个回答

7

使用以下代码检测方向:

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

1
您可以监听广播ACTION_CONFIGURATION_CHANGED,当当前设备的配置(方向、语言环境等)发生改变时,Android系统会发送该广播。 根据文档: 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 中稍后也会遇到 NPE,因为 mOrientationChangeReceiver 对于新的提供程序实例为空。 应用小部件是临时上下文,因此在此情况下不适合注册接收器。 - Tom

1
自 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 ...
}

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

0
使用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 -->


1
事实是,我所指的是一个应用小部件,而不是一个活动。 - drmrbrewer

0

检查一下这段代码,它是有效的:

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

   }
  });

1
设置一个按钮的OnClickListener与问题的相关性是什么? - drmrbrewer
当我们实时旋转并重新启动活动时,它会检测到onclick而不是onconfiguration更改。 - Androider
仅在主屏幕设置中允许屏幕旋转时才有效。 - t0m

-1
你可以使用以下代码片段中所做的小部件宽度和高度来检查它:
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; 
    } 
} 

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